@ulu/frontend-vue 0.1.0-beta.7 → 0.1.0-beta.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,9 +3,7 @@
3
3
  <slot v-else name="mobile" />
4
4
  </template>
5
5
 
6
- <script>
7
- export default {
8
- name: "AdaptiveLayout",
9
- inject: ["uluIsMobile"],
10
- };
6
+ <script setup>
7
+ import { useRequiredInject } from '../../composables/useRequiredInject.js';
8
+ const uluIsMobile = useRequiredInject('uluIsMobile');
11
9
  </script>
@@ -1,5 +1,10 @@
1
1
  <template>
2
- <div class="rail rail--title-rail">
2
+ <div
3
+ class="rail rail--title-rail"
4
+ :class="{
5
+ 'rail--rule' : rule
6
+ }"
7
+ >
3
8
  <div class="rail__item rail__item--title" :class="classes.itemTitle">
4
9
  <component
5
10
  class="layout-flex type-max-width-small no-margin"
@@ -49,6 +54,7 @@
49
54
  type: String,
50
55
  default: "h2"
51
56
  },
57
+ rule: Boolean
52
58
  }
53
59
  }
54
60
  </script>
@@ -2,85 +2,79 @@
2
2
  <slot v-if="shouldShow" />
3
3
  </template>
4
4
 
5
- <script>
6
- export default {
7
- name: "UluWhenBreakpoint",
8
- inject: ["uluBreakpointManager"],
9
- props: {
10
- max: String,
11
- min: String,
12
- only: String,
13
- },
14
- data() {
15
- return {
16
- conditions: {},
17
- handlers: [],
18
- handlersSetup: false,
19
- };
20
- },
21
- computed: {
22
- shouldShow() {
23
- if (!this.handlersSetup) return false;
24
- const props = ['max', 'min', 'only'].filter(p => this[p]);
25
- if (props.length === 0) {
26
- return false;
27
- }
28
- return Object.values(this.conditions).every(c => c);
29
- },
30
- propsIdentifier() {
31
- return `${this.max || ''}-${this.min || ''}-${this.only || ''}`;
32
- }
33
- },
34
- watch: {
35
- uluBreakpointManager: {
36
- handler(manager) {
37
- if (manager && !this.handlersSetup) {
38
- this.setupHandlers(manager);
39
- }
40
- },
41
- immediate: true
42
- },
43
- propsIdentifier() {
44
- if (this.uluBreakpointManager && this.handlersSetup) {
45
- this.tearDownHandlers();
46
- this.setupHandlers(this.uluBreakpointManager);
47
- }
48
- }
49
- },
50
- methods: {
51
- setupHandlers(manager) {
52
- const setupCondition = (direction) => {
53
- const breakpointName = this[direction];
54
- if (breakpointName) {
55
- this.conditions[direction] = false;
56
- const handler = {
57
- on: () => { this.conditions[direction] = true; },
58
- off: () => { this.conditions[direction] = false; },
59
- };
60
- manager.at(breakpointName)[direction](handler);
61
- this.handlers.push({ name: breakpointName, direction, handler });
62
- }
63
- };
5
+ <script setup>
6
+ import { ref, computed, watch, onBeforeUnmount } from 'vue';
7
+ import { useRequiredInject } from '../../composables/useRequiredInject.js';
8
+
9
+ const props = defineProps({
10
+ max: String,
11
+ min: String,
12
+ only: String,
13
+ });
64
14
 
65
- setupCondition('max');
66
- setupCondition('min');
67
- setupCondition('only');
15
+ const uluBreakpointManager = useRequiredInject('uluBreakpointManager');
68
16
 
69
- this.handlersSetup = true;
70
- },
71
- tearDownHandlers() {
72
- if (this.uluBreakpointManager) {
73
- this.handlers.forEach(({ name, direction, handler }) => {
74
- this.uluBreakpointManager.at(name).remove(handler, direction);
75
- });
76
- }
77
- this.handlers = [];
78
- this.conditions = {};
79
- this.handlersSetup = false;
17
+ const conditions = ref({});
18
+ const handlers = ref([]);
19
+ const handlersSetup = ref(false);
20
+
21
+ const shouldShow = computed(() => {
22
+ if (!handlersSetup.value) return false;
23
+ const activeProps = ['max', 'min', 'only'].filter(p => props[p]);
24
+ if (activeProps.length === 0) {
25
+ return false;
26
+ }
27
+ return Object.values(conditions.value).every(c => c);
28
+ });
29
+
30
+ const setupHandlers = (manager) => {
31
+ const setupCondition = (direction) => {
32
+ const breakpointName = props[direction];
33
+ if (breakpointName) {
34
+ conditions.value[direction] = false;
35
+ const handler = {
36
+ on: () => { conditions.value[direction] = true; },
37
+ off: () => { conditions.value[direction] = false; },
38
+ };
39
+ manager.at(breakpointName)[direction](handler);
40
+ handlers.value.push({ name: breakpointName, direction, handler });
80
41
  }
81
- },
82
- beforeUnmount() {
83
- this.tearDownHandlers();
84
- },
42
+ };
43
+
44
+ setupCondition('max');
45
+ setupCondition('min');
46
+ setupCondition('only');
47
+
48
+ handlersSetup.value = true;
49
+ };
50
+
51
+ const tearDownHandlers = () => {
52
+ if (uluBreakpointManager) {
53
+ handlers.value.forEach(({ name, direction, handler }) => {
54
+ uluBreakpointManager.at(name).remove(handler, direction);
55
+ });
56
+ }
57
+ handlers.value = [];
58
+ conditions.value = {};
59
+ handlersSetup.value = false;
85
60
  };
61
+
62
+ watch(uluBreakpointManager, (manager) => {
63
+ if (manager && !handlersSetup.value) {
64
+ setupHandlers(manager);
65
+ }
66
+ }, { immediate: true });
67
+
68
+ // Watch all the props and update if they change
69
+ // - Using array syntax to avoid "deep" flag
70
+ watch([() => props.max, () => props.min, () => props.only], () => {
71
+ if (uluBreakpointManager && handlersSetup.value) {
72
+ tearDownHandlers();
73
+ setupHandlers(uluBreakpointManager);
74
+ }
75
+ });
76
+
77
+ onBeforeUnmount(() => {
78
+ tearDownHandlers();
79
+ });
86
80
  </script>
@@ -7,4 +7,5 @@
7
7
  export { useIcon } from './useIcon.js';
8
8
  export { useModifiers } from './useModifiers.js';
9
9
  export { useWindowResize } from './useWindowResize.js';
10
+ export { useRequiredInject } from './useRequiredInject.js';
10
11
  export { useBreakpointManager } from './useBreakpointManager.js';
@@ -0,0 +1,26 @@
1
+ import { inject } from 'vue';
2
+ import { injectRegistry } from "../meta.js";
3
+
4
+ // A unique sentinel object to detect if a value was provided.
5
+ // This is used to differentiate between a provider not existing vs.
6
+ // a provider explicitly giving a `null` value.
7
+ const NOT_FOUND = {};
8
+
9
+ /**
10
+ * Injects a dependency from a plugin (or other required inject) and throws an error if it's not available.
11
+ *
12
+ * @param {string} key - The injection key (e.g., 'uluBreakpointManager').
13
+ * @returns The injected value.
14
+ */
15
+ export function useRequiredInject(key) {
16
+ const dependency = inject(key, NOT_FOUND);
17
+
18
+ if (dependency === NOT_FOUND) {
19
+ const plugin = injectRegistry[key] || '';
20
+ const pluginInfo = plugin ? ` from the '${ plugin }' plugin` : "";
21
+ const action = plugin ? "Please install missing plugin." : "";
22
+ throw new Error(`Required inject: '${ key }'${ pluginInfo } was not provided. ${ action }`);
23
+ }
24
+
25
+ return dependency;
26
+ }
package/lib/meta.js ADDED
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @module lib/meta
3
+ * @description A central lookup for meta like info in the system
4
+ */
5
+
6
+ export const injectRegistry = {
7
+ 'uluCore': 'Core',
8
+ 'uluIsMobile': 'Breakpoints',
9
+ 'uluBreakpointActive': 'Breakpoints',
10
+ 'uluBreakpointDirection': 'Breakpoints',
11
+ 'uluBreakpointManager': 'Breakpoints',
12
+ 'uluModals': 'Modals',
13
+ 'uluToast': 'Toast',
14
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ulu/frontend-vue",
3
- "version": "0.1.0-beta.7",
3
+ "version": "0.1.0-beta.9",
4
4
  "description": "A modular and tree-shakeable Vue 3 component library for the Ulu frontend",
5
5
  "type": "module",
6
6
  "files": [
@@ -1,5 +1,6 @@
1
1
  export { useIcon } from "./useIcon.js";
2
2
  export { useModifiers } from "./useModifiers.js";
3
3
  export { useWindowResize } from "./useWindowResize.js";
4
+ export { useRequiredInject } from "./useRequiredInject.js";
4
5
  export { useBreakpointManager } from "./useBreakpointManager.js";
5
6
  //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Injects a dependency from a plugin (or other required inject) and throws an error if it's not available.
3
+ *
4
+ * @param {string} key - The injection key (e.g., 'uluBreakpointManager').
5
+ * @returns The injected value.
6
+ */
7
+ export function useRequiredInject(key: string): {};
8
+ //# sourceMappingURL=useRequiredInject.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useRequiredInject.d.ts","sourceRoot":"","sources":["../../lib/composables/useRequiredInject.js"],"names":[],"mappings":"AAQA;;;;;GAKG;AACH,uCAHW,MAAM,MAchB"}
@@ -0,0 +1,10 @@
1
+ export namespace injectRegistry {
2
+ let uluCore: string;
3
+ let uluIsMobile: string;
4
+ let uluBreakpointActive: string;
5
+ let uluBreakpointDirection: string;
6
+ let uluBreakpointManager: string;
7
+ let uluModals: string;
8
+ let uluToast: string;
9
+ }
10
+ //# sourceMappingURL=meta.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meta.d.ts","sourceRoot":"","sources":["../lib/meta.js"],"names":[],"mappings":""}