@threadlabs/looma 0.35.1 → 0.37.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 (60) hide show
  1. package/components/ui-avatar/ui-avatar.html +1 -1
  2. package/components/ui-avatar-group/ui-avatar-group.html +1 -1
  3. package/components/ui-button/ui-button.html +11 -4
  4. package/components/ui-color-picker/ui-color-picker.html +1 -1
  5. package/components/ui-combobox/ui-combobox.html +1 -1
  6. package/components/ui-curve-editor/ui-curve-editor.html +1 -0
  7. package/components/ui-curve-editor/ui-curve-editor.js +15 -6
  8. package/components/ui-input/ui-input.html +4 -1
  9. package/components/ui-light-editor/ui-light-editor.html +143 -19
  10. package/components/ui-light-editor/ui-light-editor.js +26 -9
  11. package/components/ui-select/ui-select.html +10 -6
  12. package/dist/index.js +1 -1
  13. package/docs/README.md +33 -7
  14. package/docs/card.js +1 -0
  15. package/docs/catalog.json +39 -5
  16. package/docs/customizer-render.mjs +27 -9
  17. package/docs/customizer.js +146 -18
  18. package/docs/fonts.mjs +45 -0
  19. package/docs/index.d.ts +2 -2
  20. package/docs/palette.mjs +67 -0
  21. package/docs/site.mjs +1 -1
  22. package/docs/theme-session.mjs +28 -9
  23. package/docs/theme.mjs +67 -26
  24. package/docs/value-editors.mjs +6 -3
  25. package/package.json +2 -2
  26. package/styles/ui-avatar-group.css +1 -1
  27. package/styles/ui-avatar.css +1 -1
  28. package/styles/ui-button.css +11 -4
  29. package/styles/ui-color-picker.css +1 -1
  30. package/styles/ui-combobox.css +2 -2
  31. package/styles/ui-input.css +4 -1
  32. package/styles/ui-light-editor.css +111 -16
  33. package/styles/ui-select.css +10 -6
  34. package/theme-system.css +17 -4
  35. package/tokens.css +28 -15
  36. package/vanilla/UiCurveEditor.d.ts +1 -0
  37. package/vanilla/UiCurveEditor.js +1 -1
  38. package/vanilla/UiLightEditor.d.ts +1 -0
  39. package/vanilla/UiLightEditor.js +2 -2
  40. package/vue/UiAvatar.vue +1 -1
  41. package/vue/UiAvatarGroup.vue +1 -1
  42. package/vue/UiButton.vue +4 -2
  43. package/vue/UiColorPicker.vue +1 -1
  44. package/vue/UiCombobox.vue +2 -2
  45. package/vue/UiCurveEditor.d.ts +6 -0
  46. package/vue/UiCurveEditor.vue +2 -0
  47. package/vue/UiInput.vue +4 -1
  48. package/vue/UiLightEditor.d.ts +8 -0
  49. package/vue/UiLightEditor.vue +22 -3
  50. package/vue/UiSelect.vue +1 -1
  51. package/vue/chunks/UiAvatar.js +1 -1
  52. package/vue/chunks/UiAvatarGroup.js +1 -1
  53. package/vue/chunks/UiButton.js +1 -1
  54. package/vue/chunks/UiColorPicker.js +1 -1
  55. package/vue/chunks/UiCombobox.js +1 -1
  56. package/vue/chunks/UiCurveEditor.js +5 -3
  57. package/vue/chunks/UiInput.js +1 -1
  58. package/vue/chunks/UiLightEditor.js +16 -6
  59. package/vue/chunks/UiSelect.js +1 -1
  60. package/vue/components.css +43 -16
package/tokens.css CHANGED
@@ -25,6 +25,9 @@
25
25
  --ui-text: #1a1a1a;
26
26
  --ui-focus-halo: 0 0 0 calc(var(--ui-focus-width) * 1.5) color-mix(in srgb, var(--ui-focus-ring) 40%, transparent);
27
27
 
28
+ /* The base type token owns the document root; rem-based roles scale from it once. */
29
+ font-size: var(--ui-font-size);
30
+
28
31
  /* Type. */
29
32
  --ui-font-sans:
30
33
  system-ui,
@@ -38,7 +41,7 @@
38
41
  "Apple Color Emoji",
39
42
  "Segoe UI Emoji";
40
43
  --ui-font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
41
- --ui-font-size: 1rem;
44
+ --ui-font-size: 16px;
42
45
  --ui-font-medium: 500;
43
46
  --ui-line-height: 1.4;
44
47
 
@@ -92,14 +95,14 @@
92
95
  --ui-accent-line-width: var(--ui-border-width);
93
96
 
94
97
  /* Type scale, from the base size. */
95
- --ui-font-size-2xs: calc(var(--ui-font-size) * 0.6875);
96
- --ui-font-size-xs: calc(var(--ui-font-size) * 0.75);
98
+ --ui-font-size-2xs: calc(1rem * 0.6875);
99
+ --ui-font-size-xs: calc(1rem * 0.75);
97
100
  /* Dense text: controls, labels, and metadata. Two steps below body copy, never one pixel. */
98
- --ui-font-size-sm: calc(var(--ui-font-size) * 0.875);
99
- --ui-font-size-md: var(--ui-font-size);
100
- --ui-font-size-lg: calc(var(--ui-font-size) * 1.125);
101
- --ui-font-size-xl: calc(var(--ui-font-size) * 1.25);
102
- --ui-font-size-2xl: calc(var(--ui-font-size) * 1.5);
101
+ --ui-font-size-sm: calc(1rem * 0.875);
102
+ --ui-font-size-md: 1rem;
103
+ --ui-font-size-lg: calc(1rem * 1.125);
104
+ --ui-font-size-xl: calc(1rem * 1.25);
105
+ --ui-font-size-2xl: calc(1rem * 1.5);
103
106
  --ui-line-height-tight: 1.2;
104
107
  --ui-line-height-md: var(--ui-line-height);
105
108
  /* Prose, not controls: the editor's document body reads at a looser line height. */
@@ -260,14 +263,14 @@
260
263
  --ui-control-size-lg: calc(var(--ui-control-size) * 1.2);
261
264
 
262
265
  /* Choice marks follow typography; row heights follow the shared control scale. */
263
- --ui-choice-mark-size: calc(var(--ui-font-size) * 1.125);
264
- --ui-choice-track-height: calc(var(--ui-font-size) * 1.5);
265
- --ui-choice-track-width: calc(var(--ui-font-size) * 2.5);
266
+ --ui-choice-mark-size: calc(1rem * 1.125);
267
+ --ui-choice-track-height: calc(1rem * 1.5);
268
+ --ui-choice-track-width: calc(1rem * 2.5);
266
269
 
267
270
  /* Icon sizes, used by icon buttons and field affordances. */
268
- --ui-icon-size-sm: var(--ui-font-size);
269
- --ui-icon-size-md: calc(var(--ui-font-size) * 1.25);
270
- --ui-icon-size-lg: calc(var(--ui-font-size) * 1.5);
271
+ --ui-icon-size-sm: 1rem;
272
+ --ui-icon-size-md: calc(1rem * 1.25);
273
+ --ui-icon-size-lg: calc(1rem * 1.5);
271
274
 
272
275
  /* Anticipatory interaction: guide → near → direct. */
273
276
  --ui-affordance-guide-size: var(--ui-space-1);
@@ -283,6 +286,15 @@
283
286
  --ui-motion-fast: 0ms;
284
287
  }
285
288
  }
289
+ /* Raise the family together on touch, so the minimum does not collapse sm and md. */
290
+ @media (pointer: coarse) {
291
+ :root, :where([data-theme], [data-contrast]) {
292
+ --ui-control-size-sm: max(calc(var(--ui-control-size) / 1.2), var(--ui-control-min-block-size));
293
+ --ui-control-size-md: calc(var(--ui-control-size-sm) * 1.2);
294
+ --ui-control-size-lg: calc(var(--ui-control-size-md) * 1.2);
295
+ }
296
+ }
297
+
286
298
  }
287
299
 
288
300
  /* The scroll fade every Looma scroller uses (see ui-scroll-area). Scroll-driven animations grow each
@@ -383,7 +395,7 @@
383
395
  background-color: var(--ui-control-surface);
384
396
  background-repeat: no-repeat;
385
397
  background-position: center;
386
- background-size: calc(var(--ui-font-size) * 0.7);
398
+ background-size: calc(1rem * 0.7);
387
399
  }
388
400
 
389
401
  [data-ui-choice-option][data-multiple][aria-selected="true"]::before {
@@ -409,4 +421,5 @@
409
421
  color: var(--ui-disabled-text);
410
422
  cursor: not-allowed;
411
423
  }
424
+
412
425
  }
@@ -2,6 +2,7 @@
2
2
  export interface UiCurveEditorEventMap {
3
3
  input: CustomEvent<{ readonly value: string }>;
4
4
  change: CustomEvent<{ readonly value: string }>;
5
+ cancel: CustomEvent<{ readonly value: string }>;
5
6
  }
6
7
  export interface UiCurveEditorElement extends HTMLSpanElement {
7
8
  addEventListener<K extends keyof UiCurveEditorEventMap>(type: K, listener: (this: UiCurveEditorElement, event: UiCurveEditorEventMap[K]) => unknown, options?: boolean | AddEventListenerOptions): void;
@@ -5,7 +5,7 @@ import "../styles/ui-curve-editor.css";
5
5
 
6
6
  const T0 = ["",[],"\n ",["span",["class","plot-frame","role","group"],["span",["class","plot"],"\n ",["svg",["viewBox","0 0 100 100","preserveAspectRatio","none","aria-hidden","true"],["path",["class","guide","d","M0 66.667 H100 M0 33.333 H100"]],["path",["class","guide","d","M0 66.667 L25 63.333"]],["path",["class","guide","d","M100 33.333 L25 33.333"]],["path",["d","M0 66.667 C25 63.333 25 33.333 100 33.333"]]],"\n ",["button",["class","handle","type","button","aria-label","First curve handle. Arrow keys adjust; Shift moves faster."],"\n "],"\n ",["button",["class","handle second","type","button","aria-label","Second curve handle. Arrow keys adjust; Shift moves faster."],"\n "],"\n "]],"\n ",["span",["class","coordinates"],"\n ",["span",["class","coordinate"],["span",[],"X1"],["ui-number-input",["data-curve-coordinate","0","min","0","max","1","step","0.01","label","First handle X"]]],"\n ",["span",["class","coordinate"],["span",[],"Y1"],["ui-number-input",["data-curve-coordinate","1","min","-1","max","2","step","0.01","label","First handle Y"]]],"\n ",["span",["class","coordinate"],["span",[],"X2"],["ui-number-input",["data-curve-coordinate","2","min","0","max","1","step","0.01","label","Second handle X"]]],"\n ",["span",["class","coordinate"],["span",[],"Y2"],["ui-number-input",["data-curve-coordinate","3","min","-1","max","2","step","0.01","label","Second handle Y"]]],"\n "],"\n ",["output",[],0],"\n "];
7
7
  let P0;
8
- const S = { n: ["point0","point1","point2","point3"], t: ["s","s","s","s"], f: import.meta.url, g: "ui-curve-editor", d: { "input": [detailCheck(checkObject([["value", checkString, false]], false)), true, true, false], "change": [detailCheck(checkObject([["value", checkString, false]], false)), true, true, false] }, x: dispatchDeclared, a: (host, I) => C(host, I), b: generatedInputs, i: ["0.25", "0.1", "0.25", "1"] };
8
+ const S = { n: ["point0","point1","point2","point3"], t: ["s","s","s","s"], f: import.meta.url, g: "ui-curve-editor", d: { "input": [detailCheck(checkObject([["value", checkString, false]], false)), true, true, false], "change": [detailCheck(checkObject([["value", checkString, false]], false)), true, true, false], "cancel": [detailCheck(checkObject([["value", checkString, false]], false)), true, true, false] }, x: dispatchDeclared, a: (host, I) => C(host, I), b: generatedInputs, i: ["0.25", "0.1", "0.25", "1"] };
9
9
  const D = { g: "ui-curve-editor", props: { "disabled": { "required":false,"default":false, c: checkBoolean, t: "boolean", j: 0, m: "b" }, "label": { "required":false,"default":"Value", c: checkString, t: "string", j: 0, m: "s" }, "size": { "required":false,"values":["sm","md","lg"],"default":"md", c: checkFormat("keyword", keywordFormat), t: "keyword", j: 0, m: ["p",formatOf(keywordFormat)] }, "value": { "required":false,"default":"cubic-bezier(0.25, 0.1, 0.25, 1)", c: checkString, t: "string", j: 0, m: "s" } } };
10
10
  const C = (host) => activateModule(controller, host);
11
11
 
@@ -2,6 +2,7 @@
2
2
  export interface UiLightEditorEventMap {
3
3
  input: CustomEvent<{ readonly x: number; readonly y: number }>;
4
4
  change: CustomEvent<{ readonly x: number; readonly y: number }>;
5
+ cancel: CustomEvent<{ readonly x: number; readonly y: number }>;
5
6
  }
6
7
  export interface UiLightEditorElement extends HTMLSpanElement {
7
8
  addEventListener<K extends keyof UiLightEditorEventMap>(type: K, listener: (this: UiLightEditorElement, event: UiLightEditorEventMap[K]) => unknown, options?: boolean | AddEventListenerOptions): void;
@@ -3,10 +3,10 @@ import { attachGeneratedController, buildTemplate, NONCONFORMING, textCall, toAt
3
3
  import * as controller from "../components/ui-light-editor/ui-light-editor.js";
4
4
  import "../styles/ui-light-editor.css";
5
5
 
6
- const T0 = ["",[],"\n ",["span",["class","stage","role","group"],"\n ",["span",["class","plane"],"\n ",["svg",["viewBox","0 0 100 60","preserveAspectRatio","none","aria-hidden","true"],["path",["d","M0 30 H100 M50 0 V60"]]],"\n ",["span",["class","specimen"],4],"\n ",["button",["type","button","class","source"]],"\n "],"\n "],"\n ",["span",["class","coordinates"],"\n ",["ui-number-input",["data-coordinate","x","min","0","max","100","step","1","unit","%","label","Light horizontal position"]],"\n ",["ui-number-input",["data-coordinate","y","min","0","max","100","step","1","unit","%","label","Light vertical position"]],"\n "],"\n ",["span",["class","hint"],"Drag the light, use arrow keys, or enter its position. Top centre is 50%, 0%."],"\n "];
6
+ const T0 = ["",[],"\n ",["span",["class","stage","role","group"],"\n ",["span",["class","plane"],"\n ",["svg",["viewBox","0 0 100 60","preserveAspectRatio","none","aria-hidden","true"],["path",["d","M0 30 H100 M50 0 V60"]]],"\n ",["span",["class","specimen"],4],"\n ",["button",["type","button","class","source"],"\n ",["span",["class","source-glyph"],["ui-icon",["name","lightbulb"]]],"\n "],"\n "],"\n "],"\n ",["span",["class","coordinates"],"\n ",["ui-number-input",["data-coordinate","x","min","0","max","100","step","1","unit","%","label","Light horizontal position"]],"\n ",["ui-number-input",["data-coordinate","y","min","0","max","100","step","1","unit","%","label","Light vertical position"]],"\n "],"\n ",["span",["class","hint"],"Drag the light, tap the background, use arrow keys, or enter its position. Escape cancels a drag. Top centre is 50%, 0%."],"\n "];
7
7
  const T1 = ["",[]];
8
8
  let P0, P1;
9
- const S = { n: ["horizontal","vertical"], t: ["s","s"], f: import.meta.url, g: "ui-light-editor", d: { "input": [detailCheck(checkObject([["x", checkNumber, false], ["y", checkNumber, false]], false)), true, true, false], "change": [detailCheck(checkObject([["x", checkNumber, false], ["y", checkNumber, false]], false)), true, true, false] }, x: dispatchDeclared, a: (host, I) => C(host, I), b: generatedInputs, i: ["50", "0"] };
9
+ const S = { n: ["horizontal","vertical"], t: ["s","s"], f: import.meta.url, g: "ui-light-editor", d: { "input": [detailCheck(checkObject([["x", checkNumber, false], ["y", checkNumber, false]], false)), true, true, false], "change": [detailCheck(checkObject([["x", checkNumber, false], ["y", checkNumber, false]], false)), true, true, false], "cancel": [detailCheck(checkObject([["x", checkNumber, false], ["y", checkNumber, false]], false)), true, true, false] }, x: dispatchDeclared, a: (host, I) => C(host, I), b: generatedInputs, i: ["50", "0"] };
10
10
  const D = { g: "ui-light-editor", props: { "disabled": { "required":false,"default":false, c: checkBoolean, t: "boolean", j: 0, m: "b" }, "label": { "required":false,"default":"Light position", c: checkString, t: "string", j: 0, m: "s" }, "size": { "required":false,"values":["sm","md","lg"],"default":"md", c: checkFormat("keyword", keywordFormat), t: "keyword", j: 0, m: ["p",formatOf(keywordFormat)] }, "x": { "required":false,"default":0.5, c: checkNumber, t: "number", j: 0, m: "n" }, "y": { "required":false,"default":0, c: checkNumber, t: "number", j: 0, m: "n" } } };
11
11
  const C = (host) => activateModule(controller, host);
12
12
 
package/vue/UiAvatar.vue CHANGED
@@ -366,7 +366,7 @@ useComponentHost(() => import('../components/ui-avatar/ui-avatar.js'), {
366
366
  inline-size: 1.25rem;
367
367
  block-size: 1.25rem;
368
368
  /* Below the type scale on purpose: two initials need room inside a 1.25rem circle. */
369
- font-size: calc(var(--ui-font-size) * 0.5625);
369
+ font-size: calc(var(--ui-font-size-md) * 0.5625);
370
370
  letter-spacing: 0.02em;
371
371
  }
372
372
 
@@ -301,7 +301,7 @@ useComponentHost(() => import('../components/ui-avatar-group/ui-avatar-group.js'
301
301
  inline-size: 1.25rem;
302
302
  block-size: 1.25rem;
303
303
  /* Matches the xs Avatar's initials. */
304
- font-size: calc(var(--ui-font-size) * 0.5625);
304
+ font-size: calc(var(--ui-font-size-md) * 0.5625);
305
305
  line-height: 1;
306
306
  }
307
307
 
package/vue/UiButton.vue CHANGED
@@ -1412,9 +1412,11 @@ useComponentHost(() => import('../components/ui-button/ui-button.js'), {
1412
1412
  border-color: transparent;
1413
1413
  }
1414
1414
  @media (pointer: coarse) {
1415
- :global(:scope:where([data-hn-ui-button])),
1415
+ :global(:scope:where([data-hn-ui-button])) {
1416
+ min-block-size: max(var(--ui-control-size-md), var(--ui-control-min-block-size));
1417
+ }
1416
1418
  :global(:scope[data-ui-button-state~="size=sm"]:where([data-hn-ui-button])) {
1417
- min-block-size: var(--ui-control-min-block-size);
1419
+ min-block-size: max(var(--ui-control-size-sm), var(--ui-control-min-block-size));
1418
1420
  }
1419
1421
  }
1420
1422
  :global(html[data-ui-input-modality="touch"]
@@ -414,7 +414,7 @@ useComponentHost(() => import('../components/ui-color-picker/ui-color-picker.js'
414
414
  --_size: max(var(--ui-control-size-md), var(--ui-control-min-block-size));
415
415
  }
416
416
  :global(:scope[data-ui-color-picker-state~="size=sm"]) {
417
- --_size: var(--ui-control-min-block-size);
417
+ --_size: max(var(--ui-control-size-sm), var(--ui-control-min-block-size));
418
418
  --_font: var(--ui-font-size-md);
419
419
  }
420
420
  }
@@ -2388,7 +2388,7 @@ useComponentHost(() => import('../components/ui-combobox/ui-combobox.js'), {
2388
2388
  /* Under touch a small field is still a touch-sized target, as a small button is, and keeps
2389
2389
  body-size text: below 16px, iOS zooms the page into the focused field. */
2390
2390
  :global(:scope[data-ui-combobox-state~="size=sm"]:where([data-hn-ui-combobox])) {
2391
- --_row: var(--ui-control-min-block-size);
2391
+ --_row: max(var(--ui-control-size-sm), var(--ui-control-min-block-size));
2392
2392
  }
2393
2393
  :global(:scope[data-ui-combobox-state~="size=sm"] input:where([data-hn-ui-combobox])) {
2394
2394
  font-size: inherit;
@@ -2739,7 +2739,7 @@ useComponentHost(() => import('../components/ui-combobox/ui-combobox.js'), {
2739
2739
  /* Under touch a small field is still a touch-sized target, as a small button is, and keeps
2740
2740
  body-size text: below 16px, iOS zooms the page into the focused field. */
2741
2741
  :global(:where(.ui-combobox)[data-ui-combobox-state~="size=sm"]:where(:scope, :not([data-hn], [data-slotted]:not([data-slotted~="ui-combobox"]))):where([data-hn-ui-combobox])) {
2742
- --_row: var(--ui-control-min-block-size);
2742
+ --_row: max(var(--ui-control-size-sm), var(--ui-control-min-block-size));
2743
2743
  }
2744
2744
  :global(:where(.ui-combobox)[data-ui-combobox-state~="size=sm"]
2745
2745
  input:where(:scope, :not([data-hn], [data-slotted]:not([data-slotted~="ui-combobox"]))):where([data-hn-ui-combobox])) {
@@ -20,6 +20,9 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
20
20
  input: (event: CustomEvent<{
21
21
  readonly value: string;
22
22
  }>) => any;
23
+ cancel: (event: CustomEvent<{
24
+ readonly value: string;
25
+ }>) => any;
23
26
  change: (event: CustomEvent<{
24
27
  readonly value: string;
25
28
  }>) => any;
@@ -44,6 +47,9 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
44
47
  onInput?: ((event: CustomEvent<{
45
48
  readonly value: string;
46
49
  }>) => any) | undefined;
50
+ onCancel?: ((event: CustomEvent<{
51
+ readonly value: string;
52
+ }>) => any) | undefined;
47
53
  onChange?: ((event: CustomEvent<{
48
54
  readonly value: string;
49
55
  }>) => any) | undefined;
@@ -136,6 +136,7 @@ const emit = defineEmits<{
136
136
  'update:value': [value: string]
137
137
  input: [event: CustomEvent<{ readonly value: string }>]
138
138
  change: [event: CustomEvent<{ readonly value: string }>]
139
+ cancel: [event: CustomEvent<{ readonly value: string }>]
139
140
  }>()
140
141
 
141
142
  const root = ref<HTMLElement | null>(null)
@@ -165,6 +166,7 @@ const dispatch = createDispatch(root, emit as (name: string, detail: unknown) =>
165
166
  checks: {
166
167
  input: isInputDetail,
167
168
  change: isInputDetail,
169
+ cancel: isInputDetail,
168
170
  },
169
171
  modeled: ['value'],
170
172
  })
package/vue/UiInput.vue CHANGED
@@ -632,7 +632,10 @@ useComponentHost(() => import('../components/ui-input/ui-input.js'), {
632
632
  :global(:scope[data-ui-input-state~="size=sm"]) {
633
633
  min-block-size: var(
634
634
  --ui-input-min-block-size,
635
- var(--_ui-default-input-min-block-size, var(--ui-control-min-block-size))
635
+ var(
636
+ --_ui-default-input-min-block-size,
637
+ max(var(--ui-control-size-sm), var(--ui-control-min-block-size))
638
+ )
636
639
  );
637
640
  }
638
641
  }
@@ -28,6 +28,10 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
28
28
  readonly x: number;
29
29
  readonly y: number;
30
30
  }>) => any;
31
+ cancel: (event: CustomEvent<{
32
+ readonly x: number;
33
+ readonly y: number;
34
+ }>) => any;
31
35
  change: (event: CustomEvent<{
32
36
  readonly x: number;
33
37
  readonly y: number;
@@ -58,6 +62,10 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
58
62
  readonly x: number;
59
63
  readonly y: number;
60
64
  }>) => any) | undefined;
65
+ onCancel?: ((event: CustomEvent<{
66
+ readonly x: number;
67
+ readonly y: number;
68
+ }>) => any) | undefined;
61
69
  onChange?: ((event: CustomEvent<{
62
70
  readonly x: number;
63
71
  readonly y: number;
@@ -23,6 +23,7 @@ import {
23
23
  vPropValidity,
24
24
  vuePropInputs,
25
25
  } from './props'
26
+ import UiIcon from './UiIcon.vue'
26
27
  import UiNumberInput from './UiNumberInput.vue'
27
28
 
28
29
  defineOptions({ inheritAttrs: false })
@@ -148,6 +149,7 @@ const emit = defineEmits<{
148
149
  'update:y': [value: number]
149
150
  input: [event: CustomEvent<{ readonly x: number; readonly y: number }>]
150
151
  change: [event: CustomEvent<{ readonly x: number; readonly y: number }>]
152
+ cancel: [event: CustomEvent<{ readonly x: number; readonly y: number }>]
151
153
  }>()
152
154
 
153
155
  const root = ref<HTMLElement | null>(null)
@@ -180,6 +182,7 @@ const dispatch = createDispatch(root, emit as (name: string, detail: unknown) =>
180
182
  checks: {
181
183
  input: isInputDetail,
182
184
  change: isInputDetail,
185
+ cancel: isInputDetail,
183
186
  },
184
187
  modeled: ['x', 'y'],
185
188
  })
@@ -255,6 +258,10 @@ useComponentHost(() => import('../components/ui-light-editor/ui-light-editor.js'
255
258
  :aria-label="guarded"
256
259
  ref="sourceElement"
257
260
  >
261
+ <span class="source-glyph" data-hn-ui-light-editor><UiIcon
262
+ class="ui-icon"
263
+ name="lightbulb"
264
+ /></span>
258
265
  </button></span></span>{{ ' ' }}<span
259
266
  class="coordinates"
260
267
  data-hn-ui-light-editor
@@ -293,7 +300,8 @@ useComponentHost(() => import('../components/ui-light-editor/ui-light-editor.js'
293
300
  },
294
301
  }"
295
302
  /></span>{{ ' ' }}<span class="hint" data-hn-ui-light-editor
296
- >Drag the light, use arrow keys, or enter its position. Top centre is 50%, 0%.</span></span>
303
+ >Drag the light, tap the background, use arrow keys, or enter its position. Escape cancels a
304
+ drag. Top centre is 50%, 0%.</span></span>
297
305
  </template>
298
306
 
299
307
  <style scoped>
@@ -354,10 +362,18 @@ useComponentHost(() => import('../components/ui-light-editor/ui-light-editor.js'
354
362
  cursor: grab;
355
363
  touch-action: none;
356
364
  }
365
+ :global(.source-glyph:where([data-hn-ui-light-editor])) {
366
+ position: relative;
367
+ z-index: 1;
368
+ display: inline-flex !important;
369
+ color: var(--ui-accent);
370
+ font-size: var(--ui-font-size-lg);
371
+ }
357
372
  :global(.source:where([data-hn-ui-light-editor])::after) {
358
373
  content: "";
359
- inline-size: 1rem;
360
- block-size: 1rem;
374
+ position: absolute;
375
+ inline-size: 2rem;
376
+ block-size: 2rem;
361
377
  border: var(--ui-border-width) solid var(--ui-accent);
362
378
  border-radius: 50%;
363
379
  background: var(--ui-surface-raised);
@@ -390,6 +406,9 @@ useComponentHost(() => import('../components/ui-light-editor/ui-light-editor.js'
390
406
  color: var(--ui-text-secondary);
391
407
  }
392
408
  @media (forced-colors: active) {
409
+ :global(.source-glyph:where([data-hn-ui-light-editor])) {
410
+ color: CanvasText;
411
+ }
393
412
  :global(.source:where([data-hn-ui-light-editor])::after) {
394
413
  background: Canvas;
395
414
  border-color: CanvasText;
package/vue/UiSelect.vue CHANGED
@@ -386,7 +386,7 @@ useComponentHost(() => import('../components/ui-select/ui-select.js'), {
386
386
  }
387
387
 
388
388
  :global(:scope[data-ui-select-state~="size=sm"]:where([data-hn-ui-select])) {
389
- min-block-size: var(--ui-control-min-block-size);
389
+ min-block-size: max(var(--ui-control-size-sm), var(--ui-control-min-block-size));
390
390
  font-size: inherit;
391
391
  }
392
392
  }
@@ -336,6 +336,6 @@ var UiAvatar_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PUR
336
336
  }]]);
337
337
  };
338
338
  }
339
- }), [["__scopeId", "data-v-befec7d5"]]);
339
+ }), [["__scopeId", "data-v-d03c9917"]]);
340
340
  //#endregion
341
341
  export { UiAvatar_default as t };
@@ -229,6 +229,6 @@ var UiAvatarGroup_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @
229
229
  }]]);
230
230
  };
231
231
  }
232
- }), [["__scopeId", "data-v-2446552a"]]);
232
+ }), [["__scopeId", "data-v-a5b0148e"]]);
233
233
  //#endregion
234
234
  export { UiAvatarGroup_default as t };
@@ -866,6 +866,6 @@ var UiButton_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PUR
866
866
  }]]);
867
867
  };
868
868
  }
869
- }), [["__scopeId", "data-v-bb40b79e"]]);
869
+ }), [["__scopeId", "data-v-bf2aad19"]]);
870
870
  //#endregion
871
871
  export { UiButton_default as t };
@@ -321,6 +321,6 @@ var UiColorPicker_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @
321
321
  }]]);
322
322
  };
323
323
  }
324
- }), [["__scopeId", "data-v-908b48a2"]]);
324
+ }), [["__scopeId", "data-v-b2a9e21e"]]);
325
325
  //#endregion
326
326
  export { UiColorPicker_default as t };
@@ -2134,6 +2134,6 @@ var UiCombobox_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__P
2134
2134
  }]]);
2135
2135
  };
2136
2136
  }
2137
- }), [["__scopeId", "data-v-ee406b40"]]);
2137
+ }), [["__scopeId", "data-v-85d2ac14"]]);
2138
2138
  //#endregion
2139
2139
  export { UiCombobox_default as t };
@@ -37,7 +37,8 @@ var UiCurveEditor_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @
37
37
  emits: [
38
38
  "update:value",
39
39
  "input",
40
- "change"
40
+ "change",
41
+ "cancel"
41
42
  ],
42
43
  setup(__props, { emit: __emit }) {
43
44
  const propValidityContract = { props: {
@@ -164,7 +165,8 @@ var UiCurveEditor_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @
164
165
  const dispatch = createDispatch(root, emit, {
165
166
  checks: {
166
167
  input: isInputDetail,
167
- change: isInputDetail
168
+ change: isInputDetail,
169
+ cancel: isInputDetail
168
170
  },
169
171
  modeled: ["value"]
170
172
  });
@@ -408,6 +410,6 @@ var UiCurveEditor_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @
408
410
  }]]);
409
411
  };
410
412
  }
411
- }), [["__scopeId", "data-v-b4dfbbee"]]);
413
+ }), [["__scopeId", "data-v-0eaa205c"]]);
412
414
  //#endregion
413
415
  export { UiCurveEditor_default as t };
@@ -704,6 +704,6 @@ var UiInput_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE
704
704
  }]]);
705
705
  };
706
706
  }
707
- }), [["__scopeId", "data-v-c67ac937"]]);
707
+ }), [["__scopeId", "data-v-881962d1"]]);
708
708
  //#endregion
709
709
  export { UiInput_default as t };
@@ -1,5 +1,6 @@
1
1
  import { a as concat, b as useReflectedProp, i as checkHydratedRoot, m as nativeAttrs, o as createDispatch, t as _plugin_vue_export_helper_default, y as useComponentHost } from "./_plugin-vue_export-helper.js";
2
2
  import { d as requireInputStatus, i as checkPropInput, m as vuePropInputs, p as vPropValidity, r as acceptsControllerWrite, t as BINDING_INPUTS_PROP, u as propValidityState } from "./props.js";
3
+ import { t as UiIcon_default } from "./UiIcon.js";
3
4
  import { t as UiNumberInput_default } from "./UiNumberInput.js";
4
5
  import { computed, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, getCurrentInstance, mergeProps, openBlock, provide, ref, renderSlot, toDisplayString, unref, useTemplateRef, watchSyncEffect, withDirectives } from "vue";
5
6
  //#region .build/vue/UiLightEditor.vue?vue&type=script&setup=true&lang.ts
@@ -17,6 +18,10 @@ var _hoisted_3 = {
17
18
  };
18
19
  var _hoisted_4 = ["disabled", "aria-label"];
19
20
  var _hoisted_5 = {
21
+ class: "source-glyph",
22
+ "data-hn-ui-light-editor": ""
23
+ };
24
+ var _hoisted_6 = {
20
25
  class: "coordinates",
21
26
  "data-hn-ui-light-editor": ""
22
27
  };
@@ -37,7 +42,8 @@ var UiLightEditor_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @
37
42
  "update:x",
38
43
  "update:y",
39
44
  "input",
40
- "change"
45
+ "change",
46
+ "cancel"
41
47
  ],
42
48
  setup(__props, { emit: __emit }) {
43
49
  const propValidityContract = { props: {
@@ -178,7 +184,8 @@ var UiLightEditor_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @
178
184
  const dispatch = createDispatch(root, emit, {
179
185
  checks: {
180
186
  input: isInputDetail,
181
- change: isInputDetail
187
+ change: isInputDetail,
188
+ cancel: isInputDetail
182
189
  },
183
190
  modeled: ["x", "y"]
184
191
  });
@@ -275,10 +282,13 @@ var UiLightEditor_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @
275
282
  "aria-label": guarded.value,
276
283
  ref_key: "sourceElement",
277
284
  ref: sourceElement
278
- }, null, 8, _hoisted_4)
285
+ }, [createElementVNode("span", _hoisted_5, [createVNode(UiIcon_default, {
286
+ class: "ui-icon",
287
+ name: "lightbulb"
288
+ })])], 8, _hoisted_4)
279
289
  ], 512)], 8, _hoisted_2),
280
290
  _cache[4] || (_cache[4] = createTextVNode(toDisplayString(" "), -1)),
281
- createElementVNode("span", _hoisted_5, [
291
+ createElementVNode("span", _hoisted_6, [
282
292
  createVNode(UiNumberInput_default, mergeProps({
283
293
  class: "ui-number-input",
284
294
  "data-coordinate": "x",
@@ -335,13 +345,13 @@ var UiLightEditor_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @
335
345
  _cache[6] || (_cache[6] = createElementVNode("span", {
336
346
  class: "hint",
337
347
  "data-hn-ui-light-editor": ""
338
- }, "Drag the light, use arrow keys, or enter its position. Top centre is 50%, 0%.", -1))
348
+ }, "Drag the light, tap the background, use arrow keys, or enter its position. Escape cancels a drag. Top centre is 50%, 0%.", -1))
339
349
  ], 16, _hoisted_1)), [[unref(vPropValidity), {
340
350
  contract: propValidityContract,
341
351
  values: { ...props }
342
352
  }]]);
343
353
  };
344
354
  }
345
- }), [["__scopeId", "data-v-1cd5c26a"]]);
355
+ }), [["__scopeId", "data-v-dc22fbcf"]]);
346
356
  //#endregion
347
357
  export { UiLightEditor_default as t };
@@ -221,6 +221,6 @@ var UiSelect_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PUR
221
221
  }]]);
222
222
  };
223
223
  }
224
- }), [["__scopeId", "data-v-4348aae0"]]);
224
+ }), [["__scopeId", "data-v-1d116383"]]);
225
225
  //#endregion
226
226
  export { UiSelect_default as t };