@empathyco/x-components
Version:
Empathy X Components
128 lines (125 loc) • 4.1 kB
JavaScript
import { defineComponent, ref, computed, watch, onMounted } from 'vue';
import { GlobalEvents } from 'vue-global-events';
import { useXBus } from '../../../composables/use-x-bus.js';
import { throttle } from '../../../utils/throttle.js';
import { deviceXModule } from '../x-module.js';
/**
* This component helps to detect or setting a device, that can be used later to create
* different layouts optimized for different devices. This detected device is available under
* the {@link XComponentAliasAPI.device} property.
*
* @public
*/
var _sfc_main = defineComponent({
name: 'DeviceDetector',
xModule: deviceXModule.name,
components: { GlobalEvents },
props: {
/**
* Record of the device name, that can be whatever you want `xs`, `mobile`, `big`... And
* the max width in pixels for that device.
*
* @public
*/
breakpoints: {
type: Object,
default: () => ({}),
},
/**
* Forces a device, ignoring the breakpoints prop.
*
* @public
*/
force: String,
/**
* Time in milliseconds to throttle the resize events used to detect the device.
*
* @public
*/
throttleMs: {
type: Number,
default: 100,
},
},
setup(props) {
const xBus = useXBus();
/**
* The width in pixels of the window where the app is being rendered.
*
* @internal
*/
const windowWidthPx = ref(null);
/**
* Stores the window width in {@link DeviceDetector.windowWidthPx}.
*
* @internal
*/
const storeWindowWidth = () => {
windowWidthPx.value = window.innerWidth;
};
/**
* Throttled version of {@link DeviceDetector.storeWindowWidth} function.
*
* @internal
*/
let throttledStoreWindowWidth = storeWindowWidth;
/**
* List of each of the entries of the breakpoints sorted from the smallest to the biggest
* max width.
*
* @returns A list of the breakpoints sorted by its max width in ascending order.
*
* @internal
*/
const sortedBreakpoints = computed(() => Object.entries(props.breakpoints).sort(([, aWidth], [, bWidth]) => aWidth - bWidth));
/**
* The device detected by this component, or the value provided in {@link DeviceDetector.force}
* prop.
*
* @returns The detected device, or the value provided in {@link DeviceDetector.force}
* prop.
*
* @internal
*/
const detectedDevice = computed(() => {
if (props.force) {
return props.force;
}
else if (windowWidthPx.value === null) {
return null;
}
else {
return (sortedBreakpoints.value.find(([, width]) => windowWidthPx.value <= width)?.[0] ?? null);
}
});
watch(detectedDevice, device => {
xBus.emit('DeviceProvided', device);
}, { immediate: true });
/**
* Updates {@link DeviceDetector.throttledStoreWindowWidth} with the throttle time at
* {@link DeviceDetector.throttleMs}.
*
* @param throttleMs - The new duration in milliseconds for the throttle.
*
* @internal
*/
watch(() => props.throttleMs, throttleMs => {
throttledStoreWindowWidth = throttle(storeWindowWidth, throttleMs);
}, { immediate: true });
/**
* Initialises the store window width.
*
* @remarks This is done this way to ensure SSR compatibility.
*
* @internal
*/
onMounted(() => {
storeWindowWidth();
});
return {
throttledStoreWindowWidth,
};
},
});
export { _sfc_main as default };
//# sourceMappingURL=device-detector.vue2.js.map