@threadlabs/looma 0.13.5 → 0.14.0

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.
Files changed (65) hide show
  1. package/components/ui-button/ui-button.html +2 -1
  2. package/components/ui-checkbox/ui-checkbox.html +35 -0
  3. package/components/ui-combobox/ui-combobox.html +38 -3
  4. package/components/ui-icon/ui-icon.html +67 -7
  5. package/components/ui-input/ui-input.html +27 -0
  6. package/components/ui-input-group/ui-input-group.html +15 -0
  7. package/components/ui-radio/ui-radio.html +35 -0
  8. package/components/ui-select/ui-select.html +29 -3
  9. package/components/ui-switch/ui-switch.html +36 -0
  10. package/components/ui-textarea/ui-textarea.html +20 -0
  11. package/dist/index.js +17 -18
  12. package/package.json +1 -1
  13. package/styles/ui-button.css +3 -1
  14. package/styles/ui-checkbox.css +38 -0
  15. package/styles/ui-combobox.css +38 -1
  16. package/styles/ui-input-group.css +20 -0
  17. package/styles/ui-input.css +29 -0
  18. package/styles/ui-radio.css +38 -0
  19. package/styles/ui-select.css +29 -3
  20. package/styles/ui-switch.css +41 -0
  21. package/styles/ui-textarea.css +21 -0
  22. package/vanilla/UiCheckbox.d.ts +1 -0
  23. package/vanilla/UiCheckbox.js +1 -1
  24. package/vanilla/UiCombobox.d.ts +1 -1
  25. package/vanilla/UiCombobox.js +1 -1
  26. package/vanilla/UiIcon.js +1 -3
  27. package/vanilla/UiInput.d.ts +1 -0
  28. package/vanilla/UiInput.js +1 -1
  29. package/vanilla/UiRadio.d.ts +1 -0
  30. package/vanilla/UiRadio.js +1 -1
  31. package/vanilla/UiSelect.d.ts +1 -0
  32. package/vanilla/UiSelect.js +1 -1
  33. package/vanilla/UiSwitch.d.ts +1 -0
  34. package/vanilla/UiSwitch.js +1 -1
  35. package/vanilla/UiTextarea.d.ts +1 -0
  36. package/vanilla/UiTextarea.js +1 -1
  37. package/vue/UiButton.vue +2 -1
  38. package/vue/UiCheckbox.d.ts +2 -0
  39. package/vue/UiCheckbox.vue +34 -0
  40. package/vue/UiCombobox.d.ts +2 -2
  41. package/vue/UiCombobox.vue +39 -2
  42. package/vue/UiIcon.vue +337 -42
  43. package/vue/UiInput.d.ts +2 -0
  44. package/vue/UiInput.vue +41 -0
  45. package/vue/UiInputGroup.vue +15 -0
  46. package/vue/UiRadio.d.ts +2 -0
  47. package/vue/UiRadio.vue +34 -0
  48. package/vue/UiSelect.d.ts +2 -0
  49. package/vue/UiSelect.vue +34 -3
  50. package/vue/UiSwitch.d.ts +2 -0
  51. package/vue/UiSwitch.vue +35 -0
  52. package/vue/UiTextarea.d.ts +2 -0
  53. package/vue/UiTextarea.vue +27 -0
  54. package/vue/chunks/UiButton.js +1 -1
  55. package/vue/chunks/UiCheckbox.js +3 -2
  56. package/vue/chunks/UiCombobox.js +1 -1
  57. package/vue/chunks/UiIcon.js +950 -32
  58. package/vue/chunks/UiInput.js +7 -2
  59. package/vue/chunks/UiInputGroup.js +1 -1
  60. package/vue/chunks/UiRadio.js +3 -2
  61. package/vue/chunks/UiSelect.js +7 -2
  62. package/vue/chunks/UiSwitch.js +3 -2
  63. package/vue/chunks/UiTextarea.js +7 -2
  64. package/vue/components.css +368 -168
  65. package/components/ui-icon/ui-icon.js +0 -8
package/vue/UiSelect.vue CHANGED
@@ -11,6 +11,7 @@ const props = withDefaults(
11
11
  disabled?: boolean
12
12
  invalid?: boolean
13
13
  required?: boolean
14
+ size?: 'sm' | 'md' | 'lg'
14
15
  value?: string
15
16
  modelValue?: string | null
16
17
  }>(),
@@ -18,6 +19,7 @@ const props = withDefaults(
18
19
  disabled: false,
19
20
  invalid: false,
20
21
  required: false,
22
+ size: 'md',
21
23
  },
22
24
  )
23
25
  const emit = defineEmits<{
@@ -30,6 +32,13 @@ const model = computed({
30
32
 
31
33
  const root = ref<HTMLElement | null>(null)
32
34
 
35
+ /** The values the styles' :host-state() rules test. */
36
+ const hostState = computed(() =>
37
+ [
38
+ props.size && `size size=${props.size}`,
39
+ ].filter(Boolean).join(' ')
40
+ )
41
+
33
42
  const dispatch = createDispatch(root)
34
43
 
35
44
  useComponentHost(controllerModule.default, {
@@ -47,6 +56,7 @@ useComponentHost(controllerModule.default, {
47
56
  :required="required"
48
57
  :aria-invalid="invalid"
49
58
  v-model="model"
59
+ :data-ui-select-state="hostState || undefined"
50
60
  ref="root"
51
61
  >
52
62
  <slot />
@@ -137,9 +147,30 @@ useComponentHost(controllerModule.default, {
137
147
  cursor: not-allowed;
138
148
  }
139
149
 
140
- [data-component~="ui-select"][size]:not([size="1"]) {
141
- min-block-size: 7rem;
142
- padding: var(--ui-space-2);
150
+ [data-component~="ui-select"][data-ui-select-state~="size=sm"] {
151
+ min-block-size: var(--ui-control-size-sm);
152
+ padding: var(--ui-space-1) var(--ui-space-2);
153
+ padding-inline-end: calc(var(--ui-space-2) + var(--ui-icon-size-sm) + var(--ui-space-1));
154
+ background-position: right var(--ui-space-2) center;
155
+ background-size: var(--ui-icon-size-sm) var(--ui-icon-size-sm);
156
+ font-size: var(--ui-font-size-sm);
157
+ }
158
+
159
+ [data-component~="ui-select"][data-ui-select-state~="size=lg"] {
160
+ min-block-size: var(--ui-control-size-lg);
161
+ padding: var(--ui-space-3) var(--ui-space-4);
162
+ padding-inline-end: calc(var(--ui-space-4) + 1.5rem);
163
+ background-position: right var(--ui-space-4) center;
164
+ font-size: var(--ui-font-size-md);
165
+ }
166
+
167
+ /* Under touch a small field is still a touch-sized target, as a small button is, and keeps
168
+ body-size text: below 16px, iOS zooms the page into the focused field. */
169
+ @media (pointer: coarse) {
170
+ [data-component~="ui-select"][data-ui-select-state~="size=sm"] {
171
+ min-block-size: var(--ui-control-min-block-size);
172
+ font-size: inherit;
173
+ }
143
174
  }
144
175
 
145
176
  /* A component that sets its display still honours the hidden attribute on its root. */
package/vue/UiSwitch.d.ts CHANGED
@@ -3,6 +3,7 @@ type __VLS_Props = {
3
3
  disabled?: boolean;
4
4
  name?: string;
5
5
  required?: boolean;
6
+ size?: 'sm' | 'md' | 'lg';
6
7
  value?: string;
7
8
  };
8
9
  declare var __VLS_1: {}, __VLS_3: {};
@@ -29,6 +30,7 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {},
29
30
  "onUpdate:value"?: ((value: string) => any) | undefined;
30
31
  }>, {
31
32
  name: string;
33
+ size: "sm" | "md" | "lg";
32
34
  value: string;
33
35
  disabled: boolean;
34
36
  checked: boolean;
package/vue/UiSwitch.vue CHANGED
@@ -12,6 +12,7 @@ const props = withDefaults(
12
12
  disabled?: boolean
13
13
  name?: string
14
14
  required?: boolean
15
+ size?: 'sm' | 'md' | 'lg'
15
16
  value?: string
16
17
  }>(),
17
18
  {
@@ -19,6 +20,7 @@ const props = withDefaults(
19
20
  disabled: false,
20
21
  name: '',
21
22
  required: false,
23
+ size: 'md',
22
24
  value: 'on',
23
25
  },
24
26
  )
@@ -43,6 +45,7 @@ const internalChecked = ref(false)
43
45
  const hostState = computed(() =>
44
46
  [
45
47
  props.disabled && 'disabled',
48
+ props.size && `size size=${props.size}`,
46
49
  ].filter(Boolean).join(' ')
47
50
  )
48
51
 
@@ -206,6 +209,38 @@ input:focus-visible {
206
209
  }
207
210
  }
208
211
 
212
+ /* A sized switch keeps its track and aligns instead: the label takes that size's field type size,
213
+ and the first line centres in that control height, so the label shares a row's baseline.
214
+ Multi-line labels and descriptions still grow downward from that first line. */
215
+ [data-component~="ui-switch"][data-ui-switch-state~="size=sm"] {
216
+ --_font: var(--ui-font-size-sm);
217
+ --_row: var(--ui-control-size-sm);
218
+ }
219
+
220
+ [data-component~="ui-switch"][data-ui-switch-state~="size=lg"] {
221
+ --_font: var(--ui-font-size-md);
222
+ --_row: var(--ui-control-size-lg);
223
+ }
224
+
225
+ [data-component~="ui-switch"][data-ui-switch-state~="size=sm"],
226
+ [data-component~="ui-switch"][data-ui-switch-state~="size=lg"] {
227
+ --_line: calc(var(--_font) * var(--ui-line-height-md));
228
+ font-size: var(--_font);
229
+ padding-block: calc((var(--_row) - var(--ui-switch-track-height, 1.5rem)) / 2);
230
+ }
231
+
232
+ /* The label centres on the track. */
233
+ [data-component~="ui-switch"][data-ui-switch-state~="size=sm"] .text,
234
+ [data-component~="ui-switch"][data-ui-switch-state~="size=lg"] .text {
235
+ margin-top: calc((var(--_ui-switch-track-height, 1.5rem) - var(--_line)) / 2);
236
+ }
237
+
238
+ @media (pointer: coarse) {
239
+ [data-component~="ui-switch"][data-ui-switch-state~="size=sm"] {
240
+ --_row: var(--ui-control-min-block-size);
241
+ }
242
+ }
243
+
209
244
  /* A component that sets its display still honours the hidden attribute on its root. */
210
245
  [data-component~="ui-switch"][hidden] {
211
246
  display: none;
@@ -4,6 +4,7 @@ type __VLS_Props = {
4
4
  readonly?: boolean;
5
5
  required?: boolean;
6
6
  rows?: number;
7
+ size?: 'sm' | 'md' | 'lg';
7
8
  value?: string;
8
9
  modelValue?: string | null;
9
10
  };
@@ -13,6 +14,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
13
14
  "onUpdate:modelValue"?: ((value: string) => any) | undefined;
14
15
  }>, {
15
16
  invalid: boolean;
17
+ size: "sm" | "md" | "lg";
16
18
  disabled: boolean;
17
19
  required: boolean;
18
20
  readonly: boolean;
@@ -13,6 +13,7 @@ const props = withDefaults(
13
13
  readonly?: boolean
14
14
  required?: boolean
15
15
  rows?: number
16
+ size?: 'sm' | 'md' | 'lg'
16
17
  value?: string
17
18
  modelValue?: string | null
18
19
  }>(),
@@ -22,6 +23,7 @@ const props = withDefaults(
22
23
  readonly: false,
23
24
  required: false,
24
25
  rows: 4,
26
+ size: 'md',
25
27
  },
26
28
  )
27
29
  const emit = defineEmits<{
@@ -34,6 +36,13 @@ const model = computed({
34
36
 
35
37
  const root = ref<HTMLElement | null>(null)
36
38
 
39
+ /** The values the styles' :host-state() rules test. */
40
+ const hostState = computed(() =>
41
+ [
42
+ props.size && `size size=${props.size}`,
43
+ ].filter(Boolean).join(' ')
44
+ )
45
+
37
46
  const dispatch = createDispatch(root)
38
47
 
39
48
  useComponentHost(controllerModule.default, {
@@ -53,6 +62,7 @@ useComponentHost(controllerModule.default, {
53
62
  :aria-invalid="invalid"
54
63
  :rows="rows"
55
64
  v-model="model"
65
+ :data-ui-textarea-state="hostState || undefined"
56
66
  ref="root"
57
67
  ></textarea>
58
68
  </template>
@@ -139,6 +149,23 @@ useComponentHost(controllerModule.default, {
139
149
  cursor: not-allowed;
140
150
  }
141
151
 
152
+ [data-component~="ui-textarea"][data-ui-textarea-state~="size=sm"] {
153
+ padding: var(--ui-space-1) var(--ui-space-2);
154
+ font-size: var(--ui-font-size-sm);
155
+ }
156
+
157
+ [data-component~="ui-textarea"][data-ui-textarea-state~="size=lg"] {
158
+ padding: var(--ui-space-3) var(--ui-space-4);
159
+ font-size: var(--ui-font-size-md);
160
+ }
161
+
162
+ /* Below 16px, iOS zooms the page into the focused field, so touch keeps body-size text. */
163
+ @media (pointer: coarse) {
164
+ [data-component~="ui-textarea"][data-ui-textarea-state~="size=sm"] {
165
+ font-size: inherit;
166
+ }
167
+ }
168
+
142
169
  /* A component that sets its display still honours the hidden attribute on its root. */
143
170
  [data-component~="ui-textarea"][hidden] {
144
171
  display: none;
@@ -87,6 +87,6 @@ var UiButton_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PUR
87
87
  }), [renderSlot(_ctx.$slots, "default", {}, void 0, true)], 16, _hoisted_2));
88
88
  };
89
89
  }
90
- }), [["__scopeId", "data-v-a45835c7"]]);
90
+ }), [["__scopeId", "data-v-bd32a08d"]]);
91
91
  //#endregion
92
92
  export { UiButton_default as t };
@@ -42,6 +42,7 @@ var UiCheckbox_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__P
42
42
  type: Boolean,
43
43
  default: false
44
44
  },
45
+ size: { default: "md" },
45
46
  value: { default: "on" }
46
47
  },
47
48
  emits: [
@@ -57,7 +58,7 @@ var UiCheckbox_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__P
57
58
  const descriptionElement = useTemplateRef("description");
58
59
  const internalChecked = ref(false);
59
60
  /** The values the styles' :host-state() rules test. */
60
- const hostState = computed(() => [props.disabled && "disabled"].filter(Boolean).join(" "));
61
+ const hostState = computed(() => [props.disabled && "disabled", props.size && `size size=${props.size}`].filter(Boolean).join(" "));
61
62
  const isChangeDetail = (detail) => detail !== null && typeof detail === "object" && !Array.isArray(detail) && typeof detail["checked"] === "boolean" && typeof detail["value"] === "string" && (detail["trigger"] === "keyboard" || detail["trigger"] === "pointer" || detail["trigger"] === "programmatic") && Object.keys(detail).every((key) => [
62
63
  "checked",
63
64
  "value",
@@ -94,6 +95,6 @@ var UiCheckbox_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__P
94
95
  }, null, 40, _hoisted_2), createElementVNode("span", _hoisted_3, [createElementVNode("span", _hoisted_4, [renderSlot(_ctx.$slots, "default", {}, void 0, true)]), createElementVNode("span", _hoisted_5, [renderSlot(_ctx.$slots, "description", {}, void 0, true)], 512)])], 16, _hoisted_1);
95
96
  };
96
97
  }
97
- }), [["__scopeId", "data-v-e122df08"]]);
98
+ }), [["__scopeId", "data-v-bfcc98e1"]]);
98
99
  //#endregion
99
100
  export { UiCheckbox_default as t };
@@ -488,6 +488,6 @@ var UiCombobox_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__P
488
488
  ], 16, _hoisted_1);
489
489
  };
490
490
  }
491
- }), [["__scopeId", "data-v-1482f333"]]);
491
+ }), [["__scopeId", "data-v-fd4a871f"]]);
492
492
  //#endregion
493
493
  export { UiCombobox_default as t };