@threadlabs/looma 0.33.1 → 0.34.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 (184) hide show
  1. package/components/shared/overlay.js +8 -2
  2. package/components/shared/surface-material.js +21 -0
  3. package/components/ui-button/ui-button.html +63 -47
  4. package/components/ui-card/ui-card.html +44 -2
  5. package/components/ui-curve-editor/curve.js +10 -0
  6. package/components/ui-curve-editor/ui-curve-editor.html +181 -0
  7. package/components/ui-curve-editor/ui-curve-editor.js +51 -0
  8. package/components/ui-dialog/ui-dialog.html +62 -1
  9. package/components/ui-dialog/ui-dialog.js +9 -1
  10. package/components/ui-icon-button/ui-icon-button.html +75 -23
  11. package/components/ui-menu/ui-menu.html +60 -0
  12. package/components/ui-menu/ui-menu.js +1 -1
  13. package/components/ui-number-input/arithmetic.js +47 -0
  14. package/components/ui-number-input/ui-number-input.html +62 -0
  15. package/components/ui-number-input/ui-number-input.js +44 -0
  16. package/components/ui-popover/ui-popover.html +64 -1
  17. package/components/ui-popover/ui-popover.js +1 -1
  18. package/components/ui-slider/ui-slider.html +84 -0
  19. package/components/ui-slider/ui-slider.js +29 -0
  20. package/components/ui-tabs/ui-tabs.html +6 -1
  21. package/components/ui-text/ui-text.html +31 -6
  22. package/components/ui-tooltip/ui-tooltip.html +60 -0
  23. package/components/ui-tooltip/ui-tooltip.js +1 -1
  24. package/dist/index.js +46 -43
  25. package/docs/README.md +34 -4
  26. package/docs/card.html +16 -2
  27. package/docs/card.js +17 -2
  28. package/docs/catalog.json +1154 -144
  29. package/docs/customizer-render.mjs +35 -9
  30. package/docs/customizer.js +83 -20
  31. package/docs/documentation.css +9 -1
  32. package/docs/index.d.ts +4 -2
  33. package/docs/index.mjs +1 -1
  34. package/docs/preview.js +2 -0
  35. package/docs/render.mjs +15 -6
  36. package/docs/site.mjs +50 -9
  37. package/docs/theme-session.mjs +51 -0
  38. package/docs/theme.mjs +134 -15
  39. package/docs/value-editors.mjs +33 -0
  40. package/package.json +2 -2
  41. package/styles/ui-button.css +45 -45
  42. package/styles/ui-card.css +47 -0
  43. package/styles/ui-curve-editor.css +109 -0
  44. package/styles/ui-dialog.css +132 -0
  45. package/styles/ui-icon-button.css +63 -20
  46. package/styles/ui-menu.css +72 -0
  47. package/styles/ui-number-input.css +34 -0
  48. package/styles/ui-popover.css +74 -0
  49. package/styles/ui-slider.css +53 -0
  50. package/styles/ui-tabs.css +6 -1
  51. package/styles/ui-text.css +23 -1
  52. package/styles/ui-tooltip.css +72 -0
  53. package/theme-system.css +26 -10
  54. package/tokens.css +8 -2
  55. package/vanilla/UiButton.d.ts +1 -0
  56. package/vanilla/UiButton.js +195 -130
  57. package/vanilla/UiCard.d.ts +1 -1
  58. package/vanilla/UiCard.js +1 -1
  59. package/vanilla/UiCurveEditor.d.ts +28 -0
  60. package/vanilla/UiCurveEditor.js +134 -0
  61. package/vanilla/UiIconButton.d.ts +2 -1
  62. package/vanilla/UiIconButton.js +58 -31
  63. package/vanilla/UiNumberInput.d.ts +33 -0
  64. package/vanilla/UiNumberInput.js +79 -0
  65. package/vanilla/UiSlider.d.ts +33 -0
  66. package/vanilla/UiSlider.js +125 -0
  67. package/vanilla/UiText.d.ts +2 -2
  68. package/vanilla/UiText.js +45 -11
  69. package/vanilla/index.js +3 -0
  70. package/vue/UiButton.d.ts +6 -0
  71. package/vue/UiButton.vue +155 -56
  72. package/vue/UiCard.d.ts +2 -2
  73. package/vue/UiCard.vue +55 -5
  74. package/vue/UiCurveEditor.d.ts +53 -0
  75. package/vue/UiCurveEditor.js +2 -0
  76. package/vue/UiCurveEditor.vue +427 -0
  77. package/vue/UiDialog.vue +177 -1
  78. package/vue/UiIconButton.d.ts +8 -2
  79. package/vue/UiIconButton.vue +164 -34
  80. package/vue/UiMenu.vue +89 -0
  81. package/vue/UiNumberInput.d.ts +83 -0
  82. package/vue/UiNumberInput.js +2 -0
  83. package/vue/UiNumberInput.vue +370 -0
  84. package/vue/UiPopover.vue +92 -1
  85. package/vue/UiSlider.d.ts +83 -0
  86. package/vue/UiSlider.js +2 -0
  87. package/vue/UiSlider.vue +412 -0
  88. package/vue/UiTabs.vue +6 -1
  89. package/vue/UiText.d.ts +7 -5
  90. package/vue/UiText.vue +104 -22
  91. package/vue/UiTooltip.vue +89 -0
  92. package/vue/chunks/UiActionBar.js +1 -1
  93. package/vue/chunks/UiAffordanceScope.js +2 -2
  94. package/vue/chunks/UiAvatar.js +2 -2
  95. package/vue/chunks/UiAvatarGroup.js +2 -2
  96. package/vue/chunks/UiBadge.js +2 -2
  97. package/vue/chunks/UiBreadcrumbItem.js +2 -2
  98. package/vue/chunks/UiBreadcrumbs.js +2 -2
  99. package/vue/chunks/UiButton.js +94 -11
  100. package/vue/chunks/UiCallout.js +2 -2
  101. package/vue/chunks/UiCard.js +6 -5
  102. package/vue/chunks/UiCheckbox.js +2 -2
  103. package/vue/chunks/UiCluster.js +2 -2
  104. package/vue/chunks/UiColorPicker.js +2 -2
  105. package/vue/chunks/UiCombobox.js +2 -2
  106. package/vue/chunks/UiContainer.js +2 -2
  107. package/vue/chunks/UiContextMenu.js +2 -2
  108. package/vue/chunks/UiCover.js +2 -2
  109. package/vue/chunks/UiCurveEditor.js +413 -0
  110. package/vue/chunks/UiDescriptionItem.js +2 -2
  111. package/vue/chunks/UiDescriptionList.js +2 -2
  112. package/vue/chunks/UiDialog.js +4 -4
  113. package/vue/chunks/UiDisclosure.js +2 -2
  114. package/vue/chunks/UiEditable.js +2 -2
  115. package/vue/chunks/UiEditorBlockActions.js +2 -2
  116. package/vue/chunks/UiEditorChipEditor.js +2 -2
  117. package/vue/chunks/UiEditorCodeLanguage.js +2 -2
  118. package/vue/chunks/UiEditorFootnoteEditor.js +2 -2
  119. package/vue/chunks/UiEditorImageToolbar.js +3 -3
  120. package/vue/chunks/UiEditorInsertTableGrid.js +2 -2
  121. package/vue/chunks/UiEditorLinkCard.js +3 -3
  122. package/vue/chunks/UiEditorLinkForm.js +3 -3
  123. package/vue/chunks/UiEditorMentionMenu.js +2 -2
  124. package/vue/chunks/UiEditorMentionMenuItem.js +2 -2
  125. package/vue/chunks/UiEditorSlashMenu.js +2 -2
  126. package/vue/chunks/UiEditorSlashMenuGroup.js +2 -2
  127. package/vue/chunks/UiEditorSlashMenuItem.js +2 -2
  128. package/vue/chunks/UiEditorSurface.js +2 -2
  129. package/vue/chunks/UiEditorTableContextMenu.js +2 -2
  130. package/vue/chunks/UiEditorTableOverlay.js +2 -2
  131. package/vue/chunks/UiEditorTableToolbar.js +2 -2
  132. package/vue/chunks/UiEditorToolbar.js +2 -2
  133. package/vue/chunks/UiFloatingActionButton.js +2 -2
  134. package/vue/chunks/UiFormField.js +2 -2
  135. package/vue/chunks/UiGrid.js +2 -2
  136. package/vue/chunks/UiIcon.js +2 -2
  137. package/vue/chunks/UiIconButton.js +77 -11
  138. package/vue/chunks/UiImage.js +2 -2
  139. package/vue/chunks/UiInput.js +2 -2
  140. package/vue/chunks/UiInputGroup.js +2 -2
  141. package/vue/chunks/UiList.js +2 -2
  142. package/vue/chunks/UiListItem.js +2 -2
  143. package/vue/chunks/UiListbox.js +2 -2
  144. package/vue/chunks/UiMenu.js +3 -3
  145. package/vue/chunks/UiMenuGroup.js +2 -2
  146. package/vue/chunks/UiMenuItem.js +2 -2
  147. package/vue/chunks/UiMeter.js +2 -2
  148. package/vue/chunks/UiNavItem.js +2 -2
  149. package/vue/chunks/UiNumberInput.js +390 -0
  150. package/vue/chunks/UiPageHeader.js +2 -2
  151. package/vue/chunks/UiPopover.js +4 -4
  152. package/vue/chunks/UiRadio.js +2 -2
  153. package/vue/chunks/UiRadioGroup.js +2 -2
  154. package/vue/chunks/UiReel.js +2 -2
  155. package/vue/chunks/UiScrollArea.js +2 -2
  156. package/vue/chunks/UiSearchResultRow.js +2 -2
  157. package/vue/chunks/UiSearchShell.js +2 -2
  158. package/vue/chunks/UiSection.js +2 -2
  159. package/vue/chunks/UiSelect.js +2 -2
  160. package/vue/chunks/UiSeparator.js +2 -2
  161. package/vue/chunks/UiSidebar.js +2 -2
  162. package/vue/chunks/UiSlider.js +396 -0
  163. package/vue/chunks/UiSpinner.js +2 -2
  164. package/vue/chunks/UiStack.js +2 -2
  165. package/vue/chunks/UiStatusMessage.js +2 -2
  166. package/vue/chunks/UiSwatch.js +2 -2
  167. package/vue/chunks/UiSwitch.js +2 -2
  168. package/vue/chunks/UiSwitcher.js +2 -2
  169. package/vue/chunks/UiTable.js +2 -2
  170. package/vue/chunks/UiTabs.js +3 -3
  171. package/vue/chunks/UiText.js +53 -12
  172. package/vue/chunks/UiTextarea.js +2 -2
  173. package/vue/chunks/UiToast.js +2 -2
  174. package/vue/chunks/UiToastRegion.js +2 -2
  175. package/vue/chunks/UiTooltip.js +3 -3
  176. package/vue/chunks/UiTopBar.js +1 -1
  177. package/vue/chunks/UiTree.js +2 -2
  178. package/vue/chunks/UiTreeItem.js +2 -2
  179. package/vue/chunks/_plugin-vue_export-helper.js +68 -2
  180. package/vue/chunks/props.js +24 -1
  181. package/vue/components.css +2215 -1203
  182. package/vue/editor/index.js +623 -211
  183. package/vue/index.d.ts +3 -0
  184. package/vue/index.js +5 -2
@@ -0,0 +1,53 @@
1
+ import type { PropType } from 'vue';
2
+ import { type InputBindings } from './props.js';
3
+ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
4
+ disabled: {
5
+ type: PropType<boolean | null>;
6
+ };
7
+ label: {
8
+ type: PropType<string | null>;
9
+ };
10
+ size: {
11
+ type: PropType<"sm" | "md" | "lg" | null>;
12
+ };
13
+ value: {
14
+ type: PropType<string | null>;
15
+ };
16
+ "\0htmlNextInputStatus": {
17
+ type: PropType<InputBindings>;
18
+ };
19
+ }>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
20
+ input: (event: CustomEvent<{
21
+ readonly value: string;
22
+ }>) => any;
23
+ change: (event: CustomEvent<{
24
+ readonly value: string;
25
+ }>) => any;
26
+ "update:value": (value: string) => any;
27
+ }, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
28
+ disabled: {
29
+ type: PropType<boolean | null>;
30
+ };
31
+ label: {
32
+ type: PropType<string | null>;
33
+ };
34
+ size: {
35
+ type: PropType<"sm" | "md" | "lg" | null>;
36
+ };
37
+ value: {
38
+ type: PropType<string | null>;
39
+ };
40
+ "\0htmlNextInputStatus": {
41
+ type: PropType<InputBindings>;
42
+ };
43
+ }>> & Readonly<{
44
+ onInput?: ((event: CustomEvent<{
45
+ readonly value: string;
46
+ }>) => any) | undefined;
47
+ onChange?: ((event: CustomEvent<{
48
+ readonly value: string;
49
+ }>) => any) | undefined;
50
+ "onUpdate:value"?: ((value: string) => any) | undefined;
51
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
52
+ declare const _default: typeof __VLS_export;
53
+ export default _default;
@@ -0,0 +1,2 @@
1
+ import { t as UiCurveEditor_default } from "./chunks/UiCurveEditor.js";
2
+ export { UiCurveEditor_default as default };
@@ -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>