@threadlabs/looma 0.33.1 → 0.35.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 (215) hide show
  1. package/components/shared/overlay.js +8 -2
  2. package/components/shared/surface-material.js +21 -0
  3. package/components/ui-badge/ui-badge.html +11 -3
  4. package/components/ui-button/ui-button.html +92 -51
  5. package/components/ui-card/ui-card.html +50 -6
  6. package/components/ui-checkbox/ui-checkbox.html +4 -2
  7. package/components/ui-curve-editor/curve.js +10 -0
  8. package/components/ui-curve-editor/ui-curve-editor.html +181 -0
  9. package/components/ui-curve-editor/ui-curve-editor.js +51 -0
  10. package/components/ui-dialog/ui-dialog.html +64 -1
  11. package/components/ui-dialog/ui-dialog.js +9 -1
  12. package/components/ui-icon-button/ui-icon-button.html +97 -31
  13. package/components/ui-input/ui-input.html +2 -1
  14. package/components/ui-input-group/ui-input-group.html +4 -1
  15. package/components/ui-light-editor/ui-light-editor.html +45 -0
  16. package/components/ui-light-editor/ui-light-editor.js +53 -0
  17. package/components/ui-menu/ui-menu.html +62 -0
  18. package/components/ui-menu/ui-menu.js +1 -1
  19. package/components/ui-number-input/arithmetic.js +47 -0
  20. package/components/ui-number-input/ui-number-input.html +63 -0
  21. package/components/ui-number-input/ui-number-input.js +47 -0
  22. package/components/ui-popover/ui-popover.html +66 -1
  23. package/components/ui-popover/ui-popover.js +1 -1
  24. package/components/ui-select/ui-select.html +9 -7
  25. package/components/ui-slider/ui-slider.html +84 -0
  26. package/components/ui-slider/ui-slider.js +29 -0
  27. package/components/ui-switch/ui-switch.html +3 -0
  28. package/components/ui-tabs/ui-tabs.html +6 -1
  29. package/components/ui-text/ui-text.html +31 -6
  30. package/components/ui-textarea/ui-textarea.html +2 -1
  31. package/components/ui-tooltip/ui-tooltip.html +60 -0
  32. package/components/ui-tooltip/ui-tooltip.js +1 -1
  33. package/dist/index.js +47 -43
  34. package/docs/README.md +59 -5
  35. package/docs/card.html +16 -2
  36. package/docs/card.js +17 -2
  37. package/docs/catalog.json +1640 -108
  38. package/docs/customizer-render.mjs +50 -11
  39. package/docs/customizer.js +137 -24
  40. package/docs/documentation.css +9 -1
  41. package/docs/index.d.ts +8 -3
  42. package/docs/index.mjs +1 -1
  43. package/docs/preview.js +2 -0
  44. package/docs/render.mjs +16 -7
  45. package/docs/site.mjs +78 -27
  46. package/docs/theme-session.mjs +53 -0
  47. package/docs/theme.mjs +189 -18
  48. package/docs/value-editors.mjs +33 -0
  49. package/package.json +2 -2
  50. package/styles/ui-badge.css +11 -6
  51. package/styles/ui-button.css +74 -49
  52. package/styles/ui-card.css +51 -4
  53. package/styles/ui-checkbox.css +4 -2
  54. package/styles/ui-curve-editor.css +109 -0
  55. package/styles/ui-dialog.css +136 -0
  56. package/styles/ui-icon-button.css +85 -28
  57. package/styles/ui-input-group.css +4 -1
  58. package/styles/ui-input.css +2 -1
  59. package/styles/ui-light-editor.css +28 -0
  60. package/styles/ui-menu.css +74 -0
  61. package/styles/ui-number-input.css +34 -0
  62. package/styles/ui-popover.css +76 -0
  63. package/styles/ui-select.css +9 -7
  64. package/styles/ui-slider.css +53 -0
  65. package/styles/ui-switch.css +3 -0
  66. package/styles/ui-tabs.css +6 -1
  67. package/styles/ui-text.css +23 -1
  68. package/styles/ui-textarea.css +2 -1
  69. package/styles/ui-tooltip.css +72 -0
  70. package/theme-light.css +1 -0
  71. package/theme-system.css +69 -17
  72. package/tokens.css +12 -2
  73. package/vanilla/UiButton.d.ts +1 -0
  74. package/vanilla/UiButton.js +195 -130
  75. package/vanilla/UiCard.d.ts +1 -0
  76. package/vanilla/UiCard.js +12 -12
  77. package/vanilla/UiCurveEditor.d.ts +28 -0
  78. package/vanilla/UiCurveEditor.js +134 -0
  79. package/vanilla/UiIconButton.d.ts +2 -1
  80. package/vanilla/UiIconButton.js +58 -31
  81. package/vanilla/UiLightEditor.d.ts +29 -0
  82. package/vanilla/UiLightEditor.js +102 -0
  83. package/vanilla/UiNumberInput.d.ts +33 -0
  84. package/vanilla/UiNumberInput.js +86 -0
  85. package/vanilla/UiSlider.d.ts +33 -0
  86. package/vanilla/UiSlider.js +125 -0
  87. package/vanilla/UiText.d.ts +2 -2
  88. package/vanilla/UiText.js +45 -11
  89. package/vanilla/index.js +4 -0
  90. package/vue/UiBadge.vue +29 -4
  91. package/vue/UiButton.d.ts +6 -0
  92. package/vue/UiButton.vue +188 -60
  93. package/vue/UiCard.d.ts +6 -0
  94. package/vue/UiCard.vue +80 -6
  95. package/vue/UiCheckbox.vue +4 -2
  96. package/vue/UiCurveEditor.d.ts +53 -0
  97. package/vue/UiCurveEditor.js +2 -0
  98. package/vue/UiCurveEditor.vue +427 -0
  99. package/vue/UiDialog.vue +181 -1
  100. package/vue/UiIconButton.d.ts +8 -2
  101. package/vue/UiIconButton.vue +190 -45
  102. package/vue/UiInput.vue +2 -1
  103. package/vue/UiInputGroup.vue +4 -1
  104. package/vue/UiLightEditor.d.ts +75 -0
  105. package/vue/UiLightEditor.js +2 -0
  106. package/vue/UiLightEditor.vue +402 -0
  107. package/vue/UiMenu.vue +91 -0
  108. package/vue/UiNumberInput.d.ts +83 -0
  109. package/vue/UiNumberInput.js +2 -0
  110. package/vue/UiNumberInput.vue +399 -0
  111. package/vue/UiPopover.vue +94 -1
  112. package/vue/UiSelect.vue +16 -10
  113. package/vue/UiSlider.d.ts +83 -0
  114. package/vue/UiSlider.js +2 -0
  115. package/vue/UiSlider.vue +412 -0
  116. package/vue/UiSwitch.vue +3 -0
  117. package/vue/UiTabs.vue +6 -1
  118. package/vue/UiText.d.ts +7 -5
  119. package/vue/UiText.vue +104 -22
  120. package/vue/UiTextarea.vue +2 -1
  121. package/vue/UiTooltip.vue +89 -0
  122. package/vue/chunks/UiActionBar.js +1 -1
  123. package/vue/chunks/UiAffordanceScope.js +2 -2
  124. package/vue/chunks/UiAvatar.js +2 -2
  125. package/vue/chunks/UiAvatarGroup.js +2 -2
  126. package/vue/chunks/UiBadge.js +3 -3
  127. package/vue/chunks/UiBreadcrumbItem.js +2 -2
  128. package/vue/chunks/UiBreadcrumbs.js +2 -2
  129. package/vue/chunks/UiButton.js +94 -11
  130. package/vue/chunks/UiCallout.js +2 -2
  131. package/vue/chunks/UiCard.js +34 -5
  132. package/vue/chunks/UiCheckbox.js +3 -3
  133. package/vue/chunks/UiCluster.js +2 -2
  134. package/vue/chunks/UiColorPicker.js +2 -2
  135. package/vue/chunks/UiCombobox.js +2 -2
  136. package/vue/chunks/UiContainer.js +2 -2
  137. package/vue/chunks/UiContextMenu.js +2 -2
  138. package/vue/chunks/UiCover.js +2 -2
  139. package/vue/chunks/UiCurveEditor.js +413 -0
  140. package/vue/chunks/UiDescriptionItem.js +2 -2
  141. package/vue/chunks/UiDescriptionList.js +2 -2
  142. package/vue/chunks/UiDialog.js +4 -4
  143. package/vue/chunks/UiDisclosure.js +2 -2
  144. package/vue/chunks/UiEditable.js +2 -2
  145. package/vue/chunks/UiEditorBlockActions.js +2 -2
  146. package/vue/chunks/UiEditorChipEditor.js +2 -2
  147. package/vue/chunks/UiEditorCodeLanguage.js +2 -2
  148. package/vue/chunks/UiEditorFootnoteEditor.js +2 -2
  149. package/vue/chunks/UiEditorImageToolbar.js +3 -3
  150. package/vue/chunks/UiEditorInsertTableGrid.js +2 -2
  151. package/vue/chunks/UiEditorLinkCard.js +3 -3
  152. package/vue/chunks/UiEditorLinkForm.js +3 -3
  153. package/vue/chunks/UiEditorMentionMenu.js +2 -2
  154. package/vue/chunks/UiEditorMentionMenuItem.js +2 -2
  155. package/vue/chunks/UiEditorSlashMenu.js +2 -2
  156. package/vue/chunks/UiEditorSlashMenuGroup.js +2 -2
  157. package/vue/chunks/UiEditorSlashMenuItem.js +2 -2
  158. package/vue/chunks/UiEditorSurface.js +2 -2
  159. package/vue/chunks/UiEditorTableContextMenu.js +2 -2
  160. package/vue/chunks/UiEditorTableOverlay.js +2 -2
  161. package/vue/chunks/UiEditorTableToolbar.js +2 -2
  162. package/vue/chunks/UiEditorToolbar.js +2 -2
  163. package/vue/chunks/UiFloatingActionButton.js +2 -2
  164. package/vue/chunks/UiFormField.js +2 -2
  165. package/vue/chunks/UiGrid.js +2 -2
  166. package/vue/chunks/UiIcon.js +2 -2
  167. package/vue/chunks/UiIconButton.js +77 -11
  168. package/vue/chunks/UiImage.js +2 -2
  169. package/vue/chunks/UiInput.js +3 -3
  170. package/vue/chunks/UiInputGroup.js +3 -3
  171. package/vue/chunks/UiLightEditor.js +347 -0
  172. package/vue/chunks/UiList.js +2 -2
  173. package/vue/chunks/UiListItem.js +2 -2
  174. package/vue/chunks/UiListbox.js +2 -2
  175. package/vue/chunks/UiMenu.js +3 -3
  176. package/vue/chunks/UiMenuGroup.js +2 -2
  177. package/vue/chunks/UiMenuItem.js +2 -2
  178. package/vue/chunks/UiMeter.js +2 -2
  179. package/vue/chunks/UiNavItem.js +2 -2
  180. package/vue/chunks/UiNumberInput.js +403 -0
  181. package/vue/chunks/UiPageHeader.js +2 -2
  182. package/vue/chunks/UiPopover.js +4 -4
  183. package/vue/chunks/UiRadio.js +2 -2
  184. package/vue/chunks/UiRadioGroup.js +2 -2
  185. package/vue/chunks/UiReel.js +2 -2
  186. package/vue/chunks/UiScrollArea.js +2 -2
  187. package/vue/chunks/UiSearchResultRow.js +2 -2
  188. package/vue/chunks/UiSearchShell.js +2 -2
  189. package/vue/chunks/UiSection.js +2 -2
  190. package/vue/chunks/UiSelect.js +3 -3
  191. package/vue/chunks/UiSeparator.js +2 -2
  192. package/vue/chunks/UiSidebar.js +2 -2
  193. package/vue/chunks/UiSlider.js +396 -0
  194. package/vue/chunks/UiSpinner.js +2 -2
  195. package/vue/chunks/UiStack.js +2 -2
  196. package/vue/chunks/UiStatusMessage.js +2 -2
  197. package/vue/chunks/UiSwatch.js +2 -2
  198. package/vue/chunks/UiSwitch.js +3 -3
  199. package/vue/chunks/UiSwitcher.js +2 -2
  200. package/vue/chunks/UiTable.js +2 -2
  201. package/vue/chunks/UiTabs.js +3 -3
  202. package/vue/chunks/UiText.js +53 -12
  203. package/vue/chunks/UiTextarea.js +3 -3
  204. package/vue/chunks/UiToast.js +2 -2
  205. package/vue/chunks/UiToastRegion.js +2 -2
  206. package/vue/chunks/UiTooltip.js +3 -3
  207. package/vue/chunks/UiTopBar.js +1 -1
  208. package/vue/chunks/UiTree.js +2 -2
  209. package/vue/chunks/UiTreeItem.js +2 -2
  210. package/vue/chunks/_plugin-vue_export-helper.js +68 -2
  211. package/vue/chunks/props.js +24 -1
  212. package/vue/components.css +3391 -2139
  213. package/vue/editor/index.js +623 -211
  214. package/vue/index.d.ts +4 -0
  215. package/vue/index.js +6 -2
@@ -0,0 +1,427 @@
1
+ <!-- Generated by HTML Next 1.0.0-alpha.69 for Vue 3.5. Do not edit. -->
2
+ <script setup lang="ts">
3
+ import { computed, getCurrentInstance, provide, ref, useTemplateRef, watchSyncEffect } from 'vue'
4
+ import type { PropType } from 'vue'
5
+ import {
6
+ checkHydratedRoot,
7
+ createDispatch,
8
+ nativeAttrs,
9
+ useComponentHost,
10
+ useReflectedProp,
11
+ } from './host'
12
+ import { acceptsControllerWrite } from './props'
13
+ import {
14
+ BINDING_INPUTS_PROP,
15
+ checkedProp,
16
+ checkPropInput,
17
+ type InputBindings,
18
+ propValidityState,
19
+ READY_INPUT,
20
+ requireInputStatus,
21
+ UNRESOLVED_INPUT,
22
+ vPropValidity,
23
+ vuePropInputs,
24
+ } from './props'
25
+ import UiNumberInput from './UiNumberInput.vue'
26
+
27
+ defineOptions({ inheritAttrs: false })
28
+
29
+ const propValidityContract = {
30
+ props: {
31
+ disabled: {
32
+ type: { kind: 'terminal', name: 'boolean' },
33
+ required: false,
34
+ target: { attribute: 'disabled' },
35
+ description:
36
+ 'Prevents typing, stepping and pointer or keyboard changes while keeping the value visible.',
37
+ default: false,
38
+ },
39
+ label: {
40
+ type: { kind: 'terminal', name: 'string' },
41
+ required: false,
42
+ target: { attribute: 'aria-label' },
43
+ description: 'Accessible name for the editing control.',
44
+ default: 'Value',
45
+ },
46
+ size: {
47
+ type: { kind: 'terminal', name: 'keyword' },
48
+ required: false,
49
+ target: { attribute: 'size' },
50
+ description: 'Shared field and button height.',
51
+ values: ['sm', 'md', 'lg'],
52
+ default: 'md',
53
+ },
54
+ value: {
55
+ type: { kind: 'terminal', name: 'string' },
56
+ required: false,
57
+ target: { attribute: 'value' },
58
+ description:
59
+ 'CSS cubic-bezier or a standard easing keyword. X stays within 0–1; Y is bounded to -1–2 for a limited overshoot.',
60
+ default: 'cubic-bezier(0.25, 0.1, 0.25, 1)',
61
+ },
62
+ },
63
+ } as const
64
+ const props = defineProps({
65
+ disabled: { type: null as unknown as PropType<boolean | null> },
66
+ label: { type: null as unknown as PropType<string | null> },
67
+ size: { type: null as unknown as PropType<'sm' | 'md' | 'lg' | null> },
68
+ value: { type: null as unknown as PropType<string | null> },
69
+ [BINDING_INPUTS_PROP]: { type: null as unknown as PropType<InputBindings> },
70
+ })
71
+ const acceptedProps: Record<string, unknown> = {
72
+ disabled: false,
73
+ label: 'Value',
74
+ size: 'md',
75
+ value: 'cubic-bezier(0.25, 0.1, 0.25, 1)',
76
+ }
77
+ const inputTracking = vuePropInputs(acceptedProps, {
78
+ disabled: false,
79
+ label: 'Value',
80
+ size: 'md',
81
+ value: 'cubic-bezier(0.25, 0.1, 0.25, 1)',
82
+ }, (name, value, source, values) => {
83
+ switch (name) {
84
+ case 'disabled':
85
+ return checkPropInput(value, { kind: 'terminal', name: 'boolean' }, true, true)
86
+ case 'label':
87
+ return checkPropInput(value, { kind: 'terminal', name: 'string' }, true, true)
88
+ case 'size':
89
+ return checkPropInput(value, { kind: 'terminal', name: 'keyword' }, true, true)
90
+ case 'value':
91
+ return checkPropInput(value, { kind: 'terminal', name: 'string' }, true, true)
92
+ default:
93
+ return { ok: false }
94
+ }
95
+ }, () => {
96
+ void checkedProps.value
97
+ })
98
+ const propInputs = inputTracking.inputs
99
+ const checkedProps = computed(() => {
100
+ void inputTracking.version.value
101
+ return ({
102
+ disabled: propInputs.value<boolean | null>(
103
+ 'disabled',
104
+ props['disabled'],
105
+ props[BINDING_INPUTS_PROP],
106
+ ) as boolean,
107
+ label: propInputs.value<string | null>(
108
+ 'label',
109
+ props['label'],
110
+ props[BINDING_INPUTS_PROP],
111
+ ) as string,
112
+ size: propInputs.value<'sm' | 'md' | 'lg' | null>(
113
+ 'size',
114
+ props['size'],
115
+ props[BINDING_INPUTS_PROP],
116
+ ) as 'sm' | 'md' | 'lg',
117
+ value: propInputs.value<string | null>(
118
+ 'value',
119
+ props['value'],
120
+ props[BINDING_INPUTS_PROP],
121
+ ) as string,
122
+ })
123
+ })
124
+ const inputStatus = (name: string, handlesError: boolean) => {
125
+ void checkedProps.value
126
+ void inputTracking.version.value
127
+ return requireInputStatus(propInputs.status(name), handlesError)
128
+ }
129
+ void checkedProps.value
130
+ watchSyncEffect(() => {
131
+ void checkedProps.value
132
+ })
133
+ const reflectedProp = useReflectedProp()
134
+ const hydrationInstance = getCurrentInstance()
135
+ const emit = defineEmits<{
136
+ 'update:value': [value: string]
137
+ input: [event: CustomEvent<{ readonly value: string }>]
138
+ change: [event: CustomEvent<{ readonly value: string }>]
139
+ }>()
140
+
141
+ const root = ref<HTMLElement | null>(null)
142
+ const plotElement = useTemplateRef<HTMLElement>('plotElement')
143
+ const firstLineElement = useTemplateRef<HTMLElement>('firstLineElement')
144
+ const secondLineElement = useTemplateRef<HTMLElement>('secondLineElement')
145
+ const curveElement = useTemplateRef<HTMLElement>('curveElement')
146
+ const firstElement = useTemplateRef<HTMLElement>('firstElement')
147
+ const secondElement = useTemplateRef<HTMLElement>('secondElement')
148
+ const resultElement = useTemplateRef<HTMLElement>('resultElement')
149
+ const point0 = ref('0.25')
150
+ const point1 = ref('0.1')
151
+ const point2 = ref('0.25')
152
+ const point3 = ref('1')
153
+ provide('html-next:ui-curve-editor:point0', point0)
154
+ provide('html-next:ui-curve-editor:point1', point1)
155
+ provide('html-next:ui-curve-editor:point2', point2)
156
+ provide('html-next:ui-curve-editor:point3', point3)
157
+ checkHydratedRoot('span', 'ui-curve-editor')
158
+
159
+ const isInputDetail = (
160
+ detail: unknown,
161
+ ): boolean => (detail !== null && typeof detail === 'object' && !Array.isArray(detail)
162
+ && typeof (detail as Record<string, unknown>)['value'] === 'string'
163
+ && Object.keys(detail as object).every((key) => ['value'].includes(key)))
164
+ const dispatch = createDispatch(root, emit as (name: string, detail: unknown) => void, {
165
+ checks: {
166
+ input: isInputDetail,
167
+ change: isInputDetail,
168
+ },
169
+ modeled: ['value'],
170
+ })
171
+
172
+ useComponentHost(() => import('../components/ui-curve-editor/ui-curve-editor.js'), {
173
+ root,
174
+ module: true,
175
+ dispatch,
176
+ acceptsState: (name: string, keys: readonly string[], value: unknown) =>
177
+ acceptsControllerWrite(
178
+ value,
179
+ ({
180
+ point0: { kind: 'terminal', name: 'string' },
181
+ point1: { kind: 'terminal', name: 'string' },
182
+ point2: { kind: 'terminal', name: 'string' },
183
+ point3: { kind: 'terminal', name: 'string' },
184
+ } as Record<string, any>)[name],
185
+ keys,
186
+ ),
187
+ initials: { point0: '0.25', point1: '0.1', point2: '0.25', point3: '1' },
188
+ controllerSource: {
189
+ specifier: '../components/ui-curve-editor/ui-curve-editor.js',
190
+ definition: './components/ui-curve-editor/ui-curve-editor.html',
191
+ },
192
+ props: checkedProps,
193
+ inputs: propInputs,
194
+ inputTracking,
195
+ propInputs: (name: string) => {
196
+ const incoming = hydrationInstance?.vnode.props
197
+ const kebab = name.replace(/[A-Z]/g, (letter) => '-' + letter.toLowerCase())
198
+ return incoming !== null && incoming !== undefined
199
+ ? (incoming[name] ?? incoming[kebab] ?? null)
200
+ : null
201
+ },
202
+ propNames: ['disabled', 'label', 'size', 'value'],
203
+ propValidity: (name: string) =>
204
+ propValidityState({ contract: propValidityContract, values: { ...props } }, name),
205
+ refs: {
206
+ plot: plotElement,
207
+ firstLine: firstLineElement,
208
+ secondLine: secondLineElement,
209
+ curve: curveElement,
210
+ first: firstElement,
211
+ second: secondElement,
212
+ result: resultElement,
213
+ },
214
+ state: { point0, point1, point2, point3 },
215
+ })
216
+ </script>
217
+
218
+ <template>
219
+ <span
220
+ class="ui-curve-editor"
221
+ v-bind="nativeAttrs($attrs)"
222
+ data-hn
223
+ v-prop-validity="{ contract: propValidityContract, values: { ...props } }"
224
+ :data-ui-curve-editor-prop-disabled="reflectedProp('disabled', 'disabled', checkedProps.disabled, undefined, false)"
225
+ :data-ui-curve-editor-prop-label="reflectedProp('label', 'label', checkedProps.label, undefined, false)"
226
+ :data-ui-curve-editor-prop-size="reflectedProp('size', 'size', checkedProps.size, undefined, false)"
227
+ :data-ui-curve-editor-prop-value="reflectedProp('value', 'value', checkedProps.value, undefined, false)"
228
+ ref="root"
229
+ ><span class="plot-frame" role="group" :aria-label="checkedProps.label ?? undefined"><span
230
+ class="plot"
231
+ ref="plotElement"
232
+ ><svg viewBox="0 0 100 100" preserveAspectRatio="none" aria-hidden="true">
233
+ <path class="guide" d="M0 66.667 H100 M0 33.333 H100"></path>
234
+ <path class="guide" d="M0 66.667 L25 63.333" ref="firstLineElement"></path>
235
+ <path class="guide" d="M100 33.333 L25 33.333" ref="secondLineElement"></path>
236
+ <path d="M0 66.667 C25 63.333 25 33.333 100 33.333" ref="curveElement"></path>
237
+ </svg>{{ ' ' }}<button
238
+ class="handle"
239
+ type="button"
240
+ aria-label="First curve handle. Arrow keys adjust; Shift moves faster."
241
+ :disabled="checkedProps.disabled ?? undefined"
242
+ ref="firstElement"
243
+ >
244
+ </button>{{ ' ' }}<button
245
+ class="handle second"
246
+ type="button"
247
+ aria-label="Second curve handle. Arrow keys adjust; Shift moves faster."
248
+ :disabled="checkedProps.disabled ?? undefined"
249
+ ref="secondElement"
250
+ >
251
+ </button></span></span>{{ ' ' }}<span class="coordinates"><span class="coordinate"><span
252
+ >X1</span>
253
+ <UiNumberInput
254
+ class="ui-number-input"
255
+ data-curve-coordinate="0"
256
+ :min="0"
257
+ :max="1"
258
+ :step="0.01"
259
+ label="First handle X"
260
+ :value="point0"
261
+ :size="checkedProps.size"
262
+ :disabled="checkedProps.disabled"
263
+ v-bind="{
264
+ [BINDING_INPUTS_PROP]: {
265
+ size: () => ({ value: checkedProps.size, status: inputStatus('size', true) }),
266
+ disabled: () => ({ value: checkedProps.disabled, status: inputStatus('disabled', true) }),
267
+ },
268
+ }"
269
+ /></span>{{ ' ' }}<span class="coordinate"><span>Y1</span>
270
+ <UiNumberInput
271
+ class="ui-number-input"
272
+ data-curve-coordinate="1"
273
+ :min="-1"
274
+ :max="2"
275
+ :step="0.01"
276
+ label="First handle Y"
277
+ :value="point1"
278
+ :size="checkedProps.size"
279
+ :disabled="checkedProps.disabled"
280
+ v-bind="{
281
+ [BINDING_INPUTS_PROP]: {
282
+ size: () => ({ value: checkedProps.size, status: inputStatus('size', true) }),
283
+ disabled: () => ({ value: checkedProps.disabled, status: inputStatus('disabled', true) }),
284
+ },
285
+ }"
286
+ /></span>{{ ' ' }}<span class="coordinate"><span>X2</span>
287
+ <UiNumberInput
288
+ class="ui-number-input"
289
+ data-curve-coordinate="2"
290
+ :min="0"
291
+ :max="1"
292
+ :step="0.01"
293
+ label="Second handle X"
294
+ :value="point2"
295
+ :size="checkedProps.size"
296
+ :disabled="checkedProps.disabled"
297
+ v-bind="{
298
+ [BINDING_INPUTS_PROP]: {
299
+ size: () => ({ value: checkedProps.size, status: inputStatus('size', true) }),
300
+ disabled: () => ({ value: checkedProps.disabled, status: inputStatus('disabled', true) }),
301
+ },
302
+ }"
303
+ /></span>{{ ' ' }}<span class="coordinate"><span>Y2</span>
304
+ <UiNumberInput
305
+ class="ui-number-input"
306
+ data-curve-coordinate="3"
307
+ :min="-1"
308
+ :max="2"
309
+ :step="0.01"
310
+ label="Second handle Y"
311
+ :value="point3"
312
+ :size="checkedProps.size"
313
+ :disabled="checkedProps.disabled"
314
+ v-bind="{
315
+ [BINDING_INPUTS_PROP]: {
316
+ size: () => ({ value: checkedProps.size, status: inputStatus('size', true) }),
317
+ disabled: () => ({ value: checkedProps.disabled, status: inputStatus('disabled', true) }),
318
+ },
319
+ }"
320
+ /></span></span>{{ ' ' }}<output ref="resultElement">{{
321
+ checkedProps.value
322
+ }}</output></span>
323
+ </template>
324
+
325
+ <style scoped>
326
+ @scope (.ui-curve-editor) to ([data-hn]) {
327
+ :global(:scope) {
328
+ display: grid !important;
329
+ gap: var(--ui-space-3) !important;
330
+ margin: 0 !important;
331
+ padding: 0 !important;
332
+ min-inline-size: 0;
333
+ }
334
+ :global(.plot-frame) {
335
+ box-sizing: border-box !important;
336
+ display: block !important;
337
+ block-size: 12rem;
338
+ padding: max(var(--ui-space-4), 0.75rem, calc(var(--ui-control-min-block-size) / 2)) !important;
339
+ margin: 0 !important;
340
+ border: var(--ui-border-width) solid var(--ui-control-border);
341
+ border-radius: var(--ui-field-radius, var(--ui-radius-md));
342
+ background: var(--ui-control-surface, var(--ui-surface));
343
+ }
344
+ :global(.plot) {
345
+ position: relative;
346
+ display: block !important;
347
+ inline-size: 100%;
348
+ block-size: 100%;
349
+ }
350
+ :global(svg) {
351
+ inline-size: 100%;
352
+ block-size: 100%;
353
+ overflow: visible;
354
+ }
355
+ :global(path) {
356
+ fill: none;
357
+ stroke: var(--ui-accent-solid);
358
+ stroke-width: 2;
359
+ vector-effect: non-scaling-stroke;
360
+ }
361
+ :global(.guide) {
362
+ stroke: var(--ui-control-border);
363
+ stroke-width: 1;
364
+ }
365
+ :global(.handle) {
366
+ position: absolute;
367
+ left: 25%;
368
+ top: 63.333%;
369
+ translate: -50% -50%;
370
+ inline-size: max(1.5rem, var(--ui-control-min-block-size));
371
+ block-size: max(1.5rem, var(--ui-control-min-block-size));
372
+ border: 0;
373
+ border-radius: 50%;
374
+ background: transparent;
375
+ color: var(--ui-text-primary);
376
+ touch-action: none;
377
+ cursor: grab;
378
+ padding: 0 !important;
379
+ margin: 0 !important;
380
+ }
381
+ :global(.second) {
382
+ top: 33.333%;
383
+ }
384
+ :global(.handle::after) {
385
+ content: "";
386
+ position: absolute;
387
+ inset: 25%;
388
+ border: var(--ui-border-width) solid var(--ui-accent-solid);
389
+ background: var(--ui-surface-raised);
390
+ border-radius: 50%;
391
+ box-shadow: var(--ui-shadow-xs);
392
+ }
393
+ :global(.handle::before) {
394
+ content: "";
395
+ position: absolute;
396
+ inset: 40%;
397
+ background: var(--ui-accent-solid);
398
+ border-radius: 50%;
399
+ z-index: 1;
400
+ }
401
+ :global(.handle:focus-visible) {
402
+ outline: var(--ui-focus-width) solid var(--ui-control-focus, var(--ui-accent-solid));
403
+ outline-offset: var(--ui-space-1);
404
+ }
405
+ :global(.handle:disabled) {
406
+ cursor: not-allowed;
407
+ }
408
+ :global(.coordinates) {
409
+ display: grid !important;
410
+ grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
411
+ gap: var(--ui-space-2) !important;
412
+ }
413
+ :global(.coordinate) {
414
+ display: grid !important;
415
+ gap: var(--ui-space-1) !important;
416
+ font-size: var(--ui-font-size-sm);
417
+ }
418
+ :global(output) {
419
+ overflow-wrap: anywhere;
420
+ font-family: var(--ui-font-mono, monospace);
421
+ font-size: var(--ui-font-size-sm);
422
+ }
423
+ :global(:scope[hidden]) {
424
+ display: none !important;
425
+ }
426
+ }
427
+ </style>
package/vue/UiDialog.vue CHANGED
@@ -84,7 +84,8 @@ const propValidityContract = {
84
84
  type: { kind: 'terminal', name: 'keyword' },
85
85
  required: false,
86
86
  target: { attribute: 'size' },
87
- description: 'Choose a compact, standard, wide, or viewport-filling dialog.',
87
+ description:
88
+ 'Choose a compact, standard, wide, or viewport-filling dialog. Shared surface separation adapts to dialog purpose and rendered size.',
88
89
  values: ['sm', 'md', 'lg', 'fullscreen'],
89
90
  default: 'md',
90
91
  },
@@ -362,6 +363,9 @@ useComponentHost(() => import('../components/ui-dialog/ui-dialog.js'), {
362
363
  inherits: false;
363
364
  }
364
365
 
366
+ /* Purpose and measured size shape one shared separation lever. The content plane stays opaque;
367
+ transparency, saturation and edge light belong to the surrounding decorative material. */
368
+
365
369
  /* Own the layout wrapper; nested component roots are outside these scoped rules. */
366
370
 
367
371
  /* Alerts have no close target to add height above the title. */
@@ -387,6 +391,7 @@ useComponentHost(() => import('../components/ui-dialog/ui-dialog.js'), {
387
391
 
388
392
  @scope (.ui-dialog) to ([data-hn]) {
389
393
  :global(:scope:where([data-hn-ui-dialog])) {
394
+ --_ui-material-scale: 1;
390
395
  /* Hooks do not inherit, so the parts below read them from the root. */
391
396
  --_ui-dialog-duration: var(--ui-dialog-duration);
392
397
 
@@ -422,6 +427,93 @@ useComponentHost(() => import('../components/ui-dialog/ui-dialog.js'), {
422
427
  display var(--ui-dialog-duration, var(--ui-motion-base)) var(--ui-motion-ease) allow-discrete,
423
428
  overlay var(--ui-dialog-duration, var(--ui-motion-base)) var(--ui-motion-ease) allow-discrete;
424
429
  }
430
+ :global(:scope:where([data-hn-ui-dialog])) {
431
+ --_ui-material-glassiness: clamp(0, var(--ui-glassiness, 0), 1);
432
+ --_ui-material-separation: clamp(0, var(--ui-surface-separation, 0), 1);
433
+ --_ui-material-active: clamp(
434
+ 0,
435
+ calc((var(--_ui-material-glassiness) + var(--_ui-material-separation)) * 100000),
436
+ 1
437
+ );
438
+ --_ui-material-rim: calc(
439
+ (
440
+ var(--_ui-material-separation) + var(--_ui-material-glassiness) * 0.25
441
+ ) *
442
+ var(--_ui-material-scale, 1) *
443
+ 8px
444
+ );
445
+ --_ui-material-content-color: var(
446
+ --ui-dialog-surface,
447
+ var(--ui-material-content, var(--ui-overlay-surface, var(--ui-surface-elevated)))
448
+ );
449
+ --_ui-material-rim-color: color-mix(
450
+ in srgb,
451
+ var(--ui-material-glass, var(--ui-surface-elevated)) calc(var(--_ui-material-active) * 100%),
452
+ transparent
453
+ );
454
+ background:
455
+ var(--ui-surface-highlight, linear-gradient(transparent, transparent)) padding-box,
456
+ linear-gradient(var(--_ui-material-content-color), var(--_ui-material-content-color))
457
+ padding-box,
458
+ linear-gradient(var(--_ui-material-rim-color), var(--_ui-material-rim-color)) border-box,
459
+ var(--_ui-material-content-color) padding-box;
460
+ border-width: calc(var(--ui-border-width) + var(--_ui-material-rim));
461
+ border-color: var(
462
+ --ui-dialog-border,
463
+ color-mix(
464
+ in oklab,
465
+ var(--ui-overlay-border, var(--ui-border-strong)) calc(
466
+ (1 - var(--_ui-material-active)) * 100%
467
+ ),
468
+ transparent
469
+ )
470
+ );
471
+ box-shadow: var(
472
+ --ui-dialog-shadow,
473
+ var(
474
+ --ui-overlay-shadow,
475
+ 0 calc(var(--_ui-material-separation) * var(--_ui-material-scale, 1) * 8px) calc(
476
+ var(--_ui-material-separation) * var(--_ui-material-scale, 1) * 24px
477
+ ) color-mix(in oklab, var(--ui-text-primary) 15%, transparent),
478
+ var(--ui-material-glow, 0 0 transparent),
479
+ inset 0 0 0 calc(var(--_ui-material-active) * var(--ui-border-width)) var(
480
+ --ui-material-edge,
481
+ var(--ui-border-strong)
482
+ ),
483
+ var(--ui-elevation-dialog, var(--ui-shadow-xl))
484
+ )
485
+ );
486
+ backdrop-filter: blur(
487
+ calc(var(--_ui-material-glassiness) * var(--_ui-material-scale, 1) * 18px)
488
+ ) saturate(calc(1 + var(--_ui-material-glassiness) * var(--_ui-material-scale, 1) * 0.18));
489
+ -webkit-backdrop-filter: blur(
490
+ calc(var(--_ui-material-glassiness) * var(--_ui-material-scale, 1) * 18px)
491
+ ) saturate(calc(1 + var(--_ui-material-glassiness) * var(--_ui-material-scale, 1) * 0.18));
492
+ }
493
+
494
+ @supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
495
+ :global(:scope:where([data-hn-ui-dialog])) {
496
+ background: var(--_ui-material-content-color);
497
+ }
498
+ }
499
+
500
+ @media (prefers-reduced-transparency: reduce) {
501
+ :global(:scope:where([data-hn-ui-dialog])) {
502
+ background: var(--_ui-material-content-color);
503
+ backdrop-filter: none;
504
+ -webkit-backdrop-filter: none;
505
+ }
506
+ }
507
+
508
+ @media (forced-colors: active) {
509
+ :global(:scope:where([data-hn-ui-dialog])) {
510
+ background: Canvas;
511
+ border-color: CanvasText;
512
+ box-shadow: none;
513
+ backdrop-filter: none;
514
+ -webkit-backdrop-filter: none;
515
+ }
516
+ }
425
517
 
426
518
  :global(:scope[open]:where([data-hn-ui-dialog])) {
427
519
  display: flex !important;
@@ -578,6 +670,7 @@ useComponentHost(() => import('../components/ui-dialog/ui-dialog.js'), {
578
670
 
579
671
  @scope ([data-slotted~="ui-dialog"]:not([data-hn])) to ([data-hn], [data-slotted]) {
580
672
  :global(:where(.ui-dialog):where(:scope, :not([data-hn], [data-slotted]:not([data-slotted~="ui-dialog"]))):where([data-hn-ui-dialog])) {
673
+ --_ui-material-scale: 1;
581
674
  /* Hooks do not inherit, so the parts below read them from the root. */
582
675
  --_ui-dialog-duration: var(--ui-dialog-duration);
583
676
 
@@ -613,6 +706,93 @@ useComponentHost(() => import('../components/ui-dialog/ui-dialog.js'), {
613
706
  display var(--ui-dialog-duration, var(--ui-motion-base)) var(--ui-motion-ease) allow-discrete,
614
707
  overlay var(--ui-dialog-duration, var(--ui-motion-base)) var(--ui-motion-ease) allow-discrete;
615
708
  }
709
+ :global(:where(.ui-dialog):where(:scope, :not([data-hn], [data-slotted]:not([data-slotted~="ui-dialog"]))):where([data-hn-ui-dialog])) {
710
+ --_ui-material-glassiness: clamp(0, var(--ui-glassiness, 0), 1);
711
+ --_ui-material-separation: clamp(0, var(--ui-surface-separation, 0), 1);
712
+ --_ui-material-active: clamp(
713
+ 0,
714
+ calc((var(--_ui-material-glassiness) + var(--_ui-material-separation)) * 100000),
715
+ 1
716
+ );
717
+ --_ui-material-rim: calc(
718
+ (
719
+ var(--_ui-material-separation) + var(--_ui-material-glassiness) * 0.25
720
+ ) *
721
+ var(--_ui-material-scale, 1) *
722
+ 8px
723
+ );
724
+ --_ui-material-content-color: var(
725
+ --ui-dialog-surface,
726
+ var(--ui-material-content, var(--ui-overlay-surface, var(--ui-surface-elevated)))
727
+ );
728
+ --_ui-material-rim-color: color-mix(
729
+ in srgb,
730
+ var(--ui-material-glass, var(--ui-surface-elevated)) calc(var(--_ui-material-active) * 100%),
731
+ transparent
732
+ );
733
+ background:
734
+ var(--ui-surface-highlight, linear-gradient(transparent, transparent)) padding-box,
735
+ linear-gradient(var(--_ui-material-content-color), var(--_ui-material-content-color))
736
+ padding-box,
737
+ linear-gradient(var(--_ui-material-rim-color), var(--_ui-material-rim-color)) border-box,
738
+ var(--_ui-material-content-color) padding-box;
739
+ border-width: calc(var(--ui-border-width) + var(--_ui-material-rim));
740
+ border-color: var(
741
+ --ui-dialog-border,
742
+ color-mix(
743
+ in oklab,
744
+ var(--ui-overlay-border, var(--ui-border-strong)) calc(
745
+ (1 - var(--_ui-material-active)) * 100%
746
+ ),
747
+ transparent
748
+ )
749
+ );
750
+ box-shadow: var(
751
+ --ui-dialog-shadow,
752
+ var(
753
+ --ui-overlay-shadow,
754
+ 0 calc(var(--_ui-material-separation) * var(--_ui-material-scale, 1) * 8px) calc(
755
+ var(--_ui-material-separation) * var(--_ui-material-scale, 1) * 24px
756
+ ) color-mix(in oklab, var(--ui-text-primary) 15%, transparent),
757
+ var(--ui-material-glow, 0 0 transparent),
758
+ inset 0 0 0 calc(var(--_ui-material-active) * var(--ui-border-width)) var(
759
+ --ui-material-edge,
760
+ var(--ui-border-strong)
761
+ ),
762
+ var(--ui-elevation-dialog, var(--ui-shadow-xl))
763
+ )
764
+ );
765
+ backdrop-filter: blur(
766
+ calc(var(--_ui-material-glassiness) * var(--_ui-material-scale, 1) * 18px)
767
+ ) saturate(calc(1 + var(--_ui-material-glassiness) * var(--_ui-material-scale, 1) * 0.18));
768
+ -webkit-backdrop-filter: blur(
769
+ calc(var(--_ui-material-glassiness) * var(--_ui-material-scale, 1) * 18px)
770
+ ) saturate(calc(1 + var(--_ui-material-glassiness) * var(--_ui-material-scale, 1) * 0.18));
771
+ }
772
+
773
+ @supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
774
+ :global(:where(.ui-dialog):where(:scope, :not([data-hn], [data-slotted]:not([data-slotted~="ui-dialog"]))):where([data-hn-ui-dialog])) {
775
+ background: var(--_ui-material-content-color);
776
+ }
777
+ }
778
+
779
+ @media (prefers-reduced-transparency: reduce) {
780
+ :global(:where(.ui-dialog):where(:scope, :not([data-hn], [data-slotted]:not([data-slotted~="ui-dialog"]))):where([data-hn-ui-dialog])) {
781
+ background: var(--_ui-material-content-color);
782
+ backdrop-filter: none;
783
+ -webkit-backdrop-filter: none;
784
+ }
785
+ }
786
+
787
+ @media (forced-colors: active) {
788
+ :global(:where(.ui-dialog):where(:scope, :not([data-hn], [data-slotted]:not([data-slotted~="ui-dialog"]))):where([data-hn-ui-dialog])) {
789
+ background: Canvas;
790
+ border-color: CanvasText;
791
+ box-shadow: none;
792
+ backdrop-filter: none;
793
+ -webkit-backdrop-filter: none;
794
+ }
795
+ }
616
796
 
617
797
  :global(:where(.ui-dialog)[open]:where(:scope, :not([data-hn], [data-slotted]:not([data-slotted~="ui-dialog"]))):where([data-hn-ui-dialog])) {
618
798
  display: flex !important;
@@ -26,6 +26,9 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
26
26
  pending: {
27
27
  type: PropType<boolean | null>;
28
28
  };
29
+ preset: {
30
+ type: PropType<"none" | "primary" | "standard" | "quiet" | "destructive" | null>;
31
+ };
29
32
  revealed: {
30
33
  type: PropType<boolean | null>;
31
34
  };
@@ -36,7 +39,7 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
36
39
  type: PropType<"sm" | "md" | "lg" | null>;
37
40
  };
38
41
  tone: {
39
- type: PropType<"accent" | "neutral" | null>;
42
+ type: PropType<"auto" | "accent" | "neutral" | "danger" | "success" | "warning" | "info" | null>;
40
43
  };
41
44
  variant: {
42
45
  type: PropType<"ghost" | "outline" | "solid" | null>;
@@ -66,6 +69,9 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
66
69
  pending: {
67
70
  type: PropType<boolean | null>;
68
71
  };
72
+ preset: {
73
+ type: PropType<"none" | "primary" | "standard" | "quiet" | "destructive" | null>;
74
+ };
69
75
  revealed: {
70
76
  type: PropType<boolean | null>;
71
77
  };
@@ -76,7 +82,7 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
76
82
  type: PropType<"sm" | "md" | "lg" | null>;
77
83
  };
78
84
  tone: {
79
- type: PropType<"accent" | "neutral" | null>;
85
+ type: PropType<"auto" | "accent" | "neutral" | "danger" | "success" | "warning" | "info" | null>;
80
86
  };
81
87
  variant: {
82
88
  type: PropType<"ghost" | "outline" | "solid" | null>;