@threadlabs/looma 0.39.1 → 0.39.2
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.
- package/components/ui-button/ui-button.html +24 -3
- package/components/ui-checkbox/ui-checkbox.html +34 -18
- package/components/ui-light-editor/ui-light-editor.html +26 -25
- package/dist/index.js +1 -1
- package/docs/README.md +17 -6
- package/docs/catalog.json +2 -2
- package/docs/customizer-render.mjs +37 -33
- package/docs/customizer.js +82 -47
- package/docs/site.mjs +1 -1
- package/docs/theme-session.mjs +7 -8
- package/docs/theme.mjs +2 -20
- package/package.json +1 -1
- package/styles/ui-button.css +24 -1
- package/styles/ui-checkbox.css +39 -19
- package/styles/ui-light-editor.css +111 -0
- package/tokens.css +9 -2
- package/vanilla/UiButton.js +14 -12
- package/vanilla/UiLightEditor.js +2 -2
- package/vue/UiButton.vue +28 -7
- package/vue/UiCheckbox.vue +34 -19
- package/vue/UiLightEditor.vue +156 -40
- package/vue/chunks/UiButton.js +18 -10
- package/vue/chunks/UiCheckbox.js +1 -1
- package/vue/chunks/UiLightEditor.js +66 -58
- package/vue/components.css +232 -42
- package/vue/editor/index.js +46 -36
package/docs/theme.mjs
CHANGED
|
@@ -49,9 +49,9 @@ const starting = values => ({ schemaVersion: 1, values: { ...defaultRecipe().val
|
|
|
49
49
|
export const startingPoints = {
|
|
50
50
|
clear: defaultRecipe(),
|
|
51
51
|
bookish: starting({ rhythm: '1.05', action: '#2e1228', canvas: '#f7f7f5', surface: '#fffefd', text: '#0d0c0c', 'body-font': 'Arial, sans-serif', 'display-font': 'Georgia, serif', 'text-weight': '400', 'control-roominess': '2.625', 'scale-contrast': '1.18', 'outer-depth': '1', 'inner-depth': '1', glassiness: '0.8', 'surface-separation': '0.65', translucency: '0.18', 'edge-light': '1', finish: '0.85', glow: '0.3', 'light-spread': '0.3', 'light-strength': '0.9', 'response-time': '150ms', 'response-curve': 'ease' }),
|
|
52
|
-
wiki: starting({ rhythm: '0.
|
|
52
|
+
wiki: starting({ rhythm: '0.95', 'text-weight': '400', 'space-curve': '0.8', action: '#4f46e5', canvas: '#ffffff', surface: '#ffffff', text: '#1a1a1a', 'control-roominess': '2.125', spacing: '0.95', 'scale-contrast': '1.15', 'corner-roundness': '6px', 'outer-depth': '0.35', 'inner-depth': '0', 'response-time': '110ms' }),
|
|
53
53
|
editorial: starting({ rhythm: '1.3', 'text-size': '17px', spacing: '1.12', 'space-curve': '1.4', 'scale-contrast': '1.3', action: '#182c24', canvas: '#eee9dc', surface: '#fffdf5', text: '#182c24', 'corner-roundness': '0px', 'outer-depth': '0', 'inner-depth': '0', 'body-font': 'Georgia, serif', 'display-font': 'Georgia, serif', 'text-weight': '400', 'line-weight': '2px', 'response-time': '90ms', 'response-curve': 'linear' }),
|
|
54
|
-
night: starting({ rhythm: '
|
|
54
|
+
night: starting({ rhythm: '1.05', 'display-font': 'ui-monospace, monospace', 'text-weight': '500', 'control-roominess': '2.375', spacing: '1.05', 'scale-contrast': '1.25', 'space-curve': '1', finish: '0.6', glow: '0.45', glassiness: '0.45', 'surface-separation': '0.25', 'light-x': '0.25', 'light-spread': '0.65', action: '#a7b8ff', canvas: '#11141c', surface: '#202634', text: '#edf1fb', 'corner-roundness': '12px', 'outer-depth': '1.4', 'inner-depth': '0.45', translucency: '0.2', 'edge-light': '0.65', 'response-time': '210ms', 'response-curve': 'cubic-bezier(0.2,0.8,0.2,1)' }),
|
|
55
55
|
garden: starting({ rhythm: '1.2', 'body-font': 'ui-rounded, system-ui, sans-serif', 'display-font': 'Georgia, serif', 'text-weight': '400', 'space-curve': '1.15', finish: '0.15', 'light-spread': '1', action: '#256342', canvas: '#f4edda', surface: '#fff8e7', text: '#173121', 'corner-roundness': '22px', 'outer-depth': '0.35', 'inner-depth': '0', 'edge-light': '0.2', 'control-roominess': '2.875', 'scale-contrast': '1.24', spacing: '1.05', 'response-time': '180ms', 'response-curve': 'cubic-bezier(0.16,1,0.3,1)' }),
|
|
56
56
|
};
|
|
57
57
|
export const startingPointLabels = { clear: 'Clear', bookish: 'Bookish', wiki: 'Wiki', editorial: 'Editorial', night: 'Night', garden: 'Garden' };
|
|
@@ -95,24 +95,6 @@ export function paletteFor(input) {
|
|
|
95
95
|
return Object.entries(themePalettes).find(([, palette]) => paletteKeys.every(key => values[key].toLowerCase() === palette.values[key].toLowerCase()))?.[0] ?? 'custom';
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
export const themeVariations = { warmer: 'Warmer', quieter: 'Quieter', expressive: 'More expressive', compact: 'More compact' };
|
|
99
|
-
/** Nearby choices reuse the same bounded semantics; locks protect whole decision families. */
|
|
100
|
-
export function nearbyVariation(input, kind, locks = []) {
|
|
101
|
-
const recipe = validateRecipe(input);
|
|
102
|
-
if (!Object.hasOwn(themeVariations, kind)) throw new Error('Unknown theme variation.');
|
|
103
|
-
const deltas = {
|
|
104
|
-
warmer: { warmth: .15 }, quieter: { 'color-intensity': -.12, glow: -.1, 'outer-depth': -.15 },
|
|
105
|
-
expressive: { finish: .15, 'edge-light': .15, glow: .1 }, compact: { 'control-roominess': -.15, spacing: -.1 },
|
|
106
|
-
}[kind];
|
|
107
|
-
const values = { ...recipe.values };
|
|
108
|
-
for (const [id, delta] of Object.entries(deltas)) {
|
|
109
|
-
const field = themeFields.find(item => item.id === id);
|
|
110
|
-
const family = field.family === 'Colour' ? 'palette' : field.family === 'Material' ? 'material' : 'type';
|
|
111
|
-
if (!locks.includes(family)) values[id] = String(Number(Math.max(field.min, Math.min(field.max, Number(values[id]) + delta)).toFixed(3)));
|
|
112
|
-
}
|
|
113
|
-
return validateRecipe({ ...recipe, values });
|
|
114
|
-
}
|
|
115
|
-
|
|
116
98
|
const scalar = /^[+]?(?:\d+(?:\.\d*)?|\.\d+)$/;
|
|
117
99
|
const length = /^(?:0|[+]?(?:\d+(?:\.\d*)?|\.\d+)(?:px|rem|em|ex|ch|cap|ic|lh|rlh|vw|vh|vi|vb|vmin|vmax|svw|svh|lvw|lvh|dvw|dvh|cm|mm|Q|in|pt|pc))$/;
|
|
118
100
|
const font = /^(?:"[^"\\;{}<>@\x00-\x1f]+"|'[^'\\;{}<>@\x00-\x1f]+'|[\p{L}_-][\p{L}\p{N}_ -]*)(?:\s*,\s*(?:"[^"\\;{}<>@\x00-\x1f]+"|'[^'\\;{}<>@\x00-\x1f]+'|[\p{L}_-][\p{L}\p{N}_ -]*))*$/u;
|
package/package.json
CHANGED
package/styles/ui-button.css
CHANGED
|
@@ -130,6 +130,7 @@
|
|
|
130
130
|
|
|
131
131
|
:scope:where([data-component~="ui-button"]) {
|
|
132
132
|
--_button-square-size: var(--ui-button-min-block-size, var(--ui-control-size-md));
|
|
133
|
+
box-sizing: border-box !important;
|
|
133
134
|
appearance: none;
|
|
134
135
|
min-block-size: var(--ui-button-min-block-size, var(--ui-control-size-md));
|
|
135
136
|
border-style: solid;
|
|
@@ -176,6 +177,21 @@
|
|
|
176
177
|
padding-block: var(--ui-space-0-5) !important;
|
|
177
178
|
}
|
|
178
179
|
|
|
180
|
+
/* Trim the text line itself: an anonymous flex item retains font-metric space in some fonts. */
|
|
181
|
+
.label {
|
|
182
|
+
display: block !important;
|
|
183
|
+
align-content: center !important;
|
|
184
|
+
min-inline-size: 0 !important;
|
|
185
|
+
min-block-size: 1lh !important;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.label:has(svg) {
|
|
189
|
+
display: inline-flex !important;
|
|
190
|
+
align-items: center !important;
|
|
191
|
+
gap: var(--ui-space-2) !important;
|
|
192
|
+
text-box-trim: none;
|
|
193
|
+
}
|
|
194
|
+
|
|
179
195
|
.badge {
|
|
180
196
|
display: inline-flex !important;
|
|
181
197
|
align-items: center !important;
|
|
@@ -187,7 +203,7 @@
|
|
|
187
203
|
}
|
|
188
204
|
|
|
189
205
|
@supports (text-box-trim: trim-both) {
|
|
190
|
-
:
|
|
206
|
+
.label:not(:has(svg)) {
|
|
191
207
|
text-box-trim: trim-both;
|
|
192
208
|
text-box-edge: cap alphabetic;
|
|
193
209
|
}
|
|
@@ -515,6 +531,11 @@
|
|
|
515
531
|
transition: color var(--ui-motion-fast) var(--ui-motion-ease), text-decoration-color var(--ui-motion-fast) var(--ui-motion-ease);
|
|
516
532
|
}
|
|
517
533
|
|
|
534
|
+
:scope:where([data-component~="ui-button"])[data-appearance="link"] .label {
|
|
535
|
+
display: inline !important;
|
|
536
|
+
text-box-trim: none;
|
|
537
|
+
}
|
|
538
|
+
|
|
518
539
|
:scope:where([data-component~="ui-button"])[data-appearance="link"]:hover:not(:disabled, [aria-disabled="true"]) {
|
|
519
540
|
color: var(--ui-button-link-hover-text, var(--ui-text-primary));
|
|
520
541
|
text-decoration-color: currentColor;
|
|
@@ -552,6 +573,8 @@
|
|
|
552
573
|
/* A count is an adornment, not another line of label text. Keep the standard control height
|
|
553
574
|
with enough inset for a 24px mark; large content can still grow the button naturally. */
|
|
554
575
|
|
|
576
|
+
/* Trim the text line itself: an anonymous flex item retains font-metric space in some fonts. */
|
|
577
|
+
|
|
555
578
|
@supports (text-box-trim: trim-both) {
|
|
556
579
|
}
|
|
557
580
|
|
package/styles/ui-checkbox.css
CHANGED
|
@@ -103,7 +103,8 @@
|
|
|
103
103
|
|
|
104
104
|
input:where(:not([data-component], [data-slotted]))::after {
|
|
105
105
|
content: "";
|
|
106
|
-
position: absolute;
|
|
106
|
+
position: absolute !important;
|
|
107
|
+
transform: none !important;
|
|
107
108
|
opacity: 0;
|
|
108
109
|
transition: opacity var(--ui-motion-fast) var(--ui-motion-ease);
|
|
109
110
|
}
|
|
@@ -116,43 +117,44 @@
|
|
|
116
117
|
box-shadow: var(--ui-control-inset);
|
|
117
118
|
}
|
|
118
119
|
|
|
119
|
-
/*
|
|
120
|
+
/* The SVG's painted bounds are centred in its viewBox, including its round stroke.
|
|
121
|
+
Centre that box directly; rotated border boxes do not centre the visible check. */
|
|
120
122
|
input:checked:where(:not([data-component], [data-slotted]))::after {
|
|
121
|
-
inset:
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
border-style: solid;
|
|
128
|
-
border-color: var(--ui-text-on-accent);
|
|
129
|
-
border-width: 0 calc(var(--_ui-checkbox-size) * 0.125 / 1.125) calc(var(--_ui-checkbox-size) * 0.125 / 1.125) 0;
|
|
123
|
+
inset: 50% auto auto 50% !important;
|
|
124
|
+
inline-size: calc(var(--_ui-checkbox-size) * 0.7) !important;
|
|
125
|
+
block-size: calc(var(--_ui-checkbox-size) * 0.7) !important;
|
|
126
|
+
background: var(--ui-text-on-accent);
|
|
127
|
+
mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 11.5 5 5 9-9'/%3E%3C/svg%3E")
|
|
128
|
+
center / contain no-repeat;
|
|
130
129
|
opacity: 1;
|
|
131
|
-
|
|
130
|
+
translate: -50% -50% !important;
|
|
132
131
|
animation: ui-checkbox-check var(--ui-motion-base) var(--ui-motion-ease-out, cubic-bezier(0.16, 1, 0.3, 1)) both;
|
|
133
132
|
}
|
|
134
133
|
|
|
135
134
|
input:indeterminate:where(:not([data-component], [data-slotted]))::after {
|
|
136
|
-
|
|
137
|
-
|
|
135
|
+
mask: none;
|
|
136
|
+
animation: none;
|
|
137
|
+
inset: 50% calc(var(--_ui-checkbox-size) * 0.23 / 1.125) auto !important;
|
|
138
|
+
inline-size: auto !important;
|
|
139
|
+
block-size: calc(var(--_ui-checkbox-size) * 0.125 / 1.125) !important;
|
|
138
140
|
border-radius: var(--ui-radius-round);
|
|
139
141
|
background: var(--ui-text-on-accent);
|
|
140
142
|
opacity: 1;
|
|
141
|
-
|
|
143
|
+
translate: 0 -50% !important;
|
|
142
144
|
}
|
|
143
145
|
|
|
144
146
|
@keyframes ui-checkbox-check {
|
|
145
147
|
from {
|
|
146
148
|
opacity: 0;
|
|
147
|
-
|
|
149
|
+
scale: 0.55;
|
|
148
150
|
}
|
|
149
151
|
65% {
|
|
150
152
|
opacity: 1;
|
|
151
|
-
|
|
153
|
+
scale: 1.12;
|
|
152
154
|
}
|
|
153
155
|
to {
|
|
154
156
|
opacity: 1;
|
|
155
|
-
|
|
157
|
+
scale: 1;
|
|
156
158
|
}
|
|
157
159
|
}
|
|
158
160
|
|
|
@@ -163,6 +165,20 @@
|
|
|
163
165
|
}
|
|
164
166
|
}
|
|
165
167
|
|
|
168
|
+
@media (forced-colors: active) {
|
|
169
|
+
input:checked,
|
|
170
|
+
input:indeterminate {
|
|
171
|
+
forced-color-adjust: none;
|
|
172
|
+
background: Highlight;
|
|
173
|
+
border-color: Highlight;
|
|
174
|
+
}
|
|
175
|
+
input:checked:where(:not([data-component], [data-slotted]))::after,
|
|
176
|
+
input:indeterminate:where(:not([data-component], [data-slotted]))::after {
|
|
177
|
+
forced-color-adjust: none;
|
|
178
|
+
background: HighlightText;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
166
182
|
input:hover:enabled {
|
|
167
183
|
border-color: var(--ui-accent-solid);
|
|
168
184
|
}
|
|
@@ -220,11 +236,15 @@
|
|
|
220
236
|
|
|
221
237
|
/* The label, and under it an optional line saying what the choice means. */
|
|
222
238
|
|
|
223
|
-
/*
|
|
239
|
+
/* The SVG's painted bounds are centred in its viewBox, including its round stroke.
|
|
240
|
+
Centre that box directly; rotated border boxes do not centre the visible check. */
|
|
224
241
|
|
|
225
242
|
@media (prefers-reduced-motion: reduce) {
|
|
226
243
|
}
|
|
227
244
|
|
|
245
|
+
@media (forced-colors: active) {
|
|
246
|
+
}
|
|
247
|
+
|
|
228
248
|
/* A sized choice keeps its box and aligns instead: the label takes that size's field type size,
|
|
229
249
|
and the first line centres in that control height, so the label shares a row's baseline.
|
|
230
250
|
Multi-line labels and descriptions still grow downward from that first line. */
|
|
@@ -121,3 +121,114 @@
|
|
|
121
121
|
@media (forced-colors: active) {
|
|
122
122
|
}
|
|
123
123
|
}
|
|
124
|
+
@scope ([data-slotted~="ui-light-editor"]:not([data-component])) to ([data-component], [data-slotted]) {
|
|
125
|
+
:where([data-component~="ui-light-editor"]):where(:scope, :not([data-component], [data-slotted]:not([data-slotted~="ui-light-editor"]))) {
|
|
126
|
+
display: grid !important;
|
|
127
|
+
gap: var(--ui-space-3) !important;
|
|
128
|
+
min-inline-size: 0;
|
|
129
|
+
padding: 0 !important;
|
|
130
|
+
margin: 0 !important;
|
|
131
|
+
}
|
|
132
|
+
.stage:where(:scope, :scope *) {
|
|
133
|
+
box-sizing: border-box !important;
|
|
134
|
+
display: block !important;
|
|
135
|
+
block-size: 13rem;
|
|
136
|
+
padding: calc(var(--ui-control-min-block-size) / 2) !important;
|
|
137
|
+
border: var(--ui-border-width) solid var(--ui-control-border);
|
|
138
|
+
border-radius: var(--ui-field-radius, var(--ui-radius-md));
|
|
139
|
+
background: var(--ui-neutral-surface, var(--ui-surface));
|
|
140
|
+
}
|
|
141
|
+
.plane:where(:scope, :scope *) {
|
|
142
|
+
position: relative;
|
|
143
|
+
display: block !important;
|
|
144
|
+
inline-size: 100%;
|
|
145
|
+
block-size: 100%;
|
|
146
|
+
}
|
|
147
|
+
svg:where(:scope, :scope *) {
|
|
148
|
+
inline-size: 100%;
|
|
149
|
+
block-size: 100%;
|
|
150
|
+
overflow: visible;
|
|
151
|
+
}
|
|
152
|
+
path:where(:scope, :scope *) {
|
|
153
|
+
fill: none;
|
|
154
|
+
stroke: var(--ui-border);
|
|
155
|
+
stroke-width: 1;
|
|
156
|
+
vector-effect: non-scaling-stroke;
|
|
157
|
+
}
|
|
158
|
+
.specimen:where(:scope, :scope *) {
|
|
159
|
+
position: absolute;
|
|
160
|
+
inset: 0;
|
|
161
|
+
display: grid !important;
|
|
162
|
+
place-items: center !important;
|
|
163
|
+
}
|
|
164
|
+
.source:where(:scope, :scope *) {
|
|
165
|
+
position: absolute;
|
|
166
|
+
left: 50%;
|
|
167
|
+
top: 0;
|
|
168
|
+
translate: -50% -50%;
|
|
169
|
+
display: grid !important;
|
|
170
|
+
place-items: center !important;
|
|
171
|
+
inline-size: max(2rem, var(--ui-control-min-block-size));
|
|
172
|
+
block-size: max(2rem, var(--ui-control-min-block-size));
|
|
173
|
+
padding: 0 !important;
|
|
174
|
+
margin: 0 !important;
|
|
175
|
+
border: 0;
|
|
176
|
+
border-radius: 50%;
|
|
177
|
+
background: transparent;
|
|
178
|
+
cursor: grab;
|
|
179
|
+
touch-action: none;
|
|
180
|
+
}
|
|
181
|
+
.source-glyph:where(:scope, :scope *) {
|
|
182
|
+
position: relative;
|
|
183
|
+
z-index: 1;
|
|
184
|
+
display: inline-flex !important;
|
|
185
|
+
color: var(--ui-accent);
|
|
186
|
+
font-size: var(--ui-font-size-lg);
|
|
187
|
+
}
|
|
188
|
+
.source:where(:not([data-component], [data-slotted]:not([data-slotted~="ui-light-editor"]))):where(:scope, :scope *)::after {
|
|
189
|
+
content: "";
|
|
190
|
+
position: absolute;
|
|
191
|
+
inline-size: 2rem;
|
|
192
|
+
block-size: 2rem;
|
|
193
|
+
border: var(--ui-border-width) solid var(--ui-accent);
|
|
194
|
+
border-radius: 50%;
|
|
195
|
+
background: var(--ui-surface-raised);
|
|
196
|
+
box-shadow: 0 0 0 var(--ui-space-2) color-mix(in srgb, var(--ui-accent) 12%, transparent), var(--ui-shadow-sm);
|
|
197
|
+
}
|
|
198
|
+
.source:active:where(:scope, :scope *) {
|
|
199
|
+
cursor: grabbing;
|
|
200
|
+
}
|
|
201
|
+
.source:focus-visible:where(:scope, :scope *) {
|
|
202
|
+
outline: var(--ui-focus-width) solid var(--ui-focus-ring);
|
|
203
|
+
outline-offset: var(--ui-space-1);
|
|
204
|
+
}
|
|
205
|
+
.source:disabled:where(:scope, :scope *) {
|
|
206
|
+
cursor: not-allowed;
|
|
207
|
+
}
|
|
208
|
+
.source:disabled:where(:not([data-component], [data-slotted]:not([data-slotted~="ui-light-editor"]))):where(:scope, :scope *)::after {
|
|
209
|
+
background: var(--ui-disabled-surface);
|
|
210
|
+
border-color: var(--ui-disabled-border);
|
|
211
|
+
box-shadow: none;
|
|
212
|
+
}
|
|
213
|
+
.coordinates:where(:scope, :scope *) {
|
|
214
|
+
display: grid !important;
|
|
215
|
+
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
|
|
216
|
+
gap: var(--ui-space-2) !important;
|
|
217
|
+
}
|
|
218
|
+
.hint:where(:scope, :scope *) {
|
|
219
|
+
font-size: var(--ui-font-size-sm);
|
|
220
|
+
color: var(--ui-text-secondary);
|
|
221
|
+
}
|
|
222
|
+
@media (forced-colors: active) {
|
|
223
|
+
.source-glyph:where(:scope, :scope *) {
|
|
224
|
+
color: CanvasText;
|
|
225
|
+
}
|
|
226
|
+
.source:where(:not([data-component], [data-slotted]:not([data-slotted~="ui-light-editor"]))):where(:scope, :scope *)::after {
|
|
227
|
+
background: Canvas;
|
|
228
|
+
border-color: CanvasText;
|
|
229
|
+
}
|
|
230
|
+
.source:focus-visible:where(:scope, :scope *) {
|
|
231
|
+
outline-color: Highlight;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
package/tokens.css
CHANGED
|
@@ -353,9 +353,12 @@
|
|
|
353
353
|
}
|
|
354
354
|
|
|
355
355
|
[data-ui-choice-option]:is(:hover, .active) {
|
|
356
|
-
background: var(--ui-
|
|
356
|
+
background: var(--ui-accent-subtle);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
[data-ui-choice-option]:focus-visible {
|
|
357
360
|
outline: var(--ui-focus-width) solid var(--ui-focus-ring);
|
|
358
|
-
outline-offset: calc(-1 * var(--ui-
|
|
361
|
+
outline-offset: calc(-1 * var(--ui-focus-width));
|
|
359
362
|
}
|
|
360
363
|
|
|
361
364
|
[data-ui-choice-option][aria-disabled="true"],
|
|
@@ -403,6 +406,10 @@
|
|
|
403
406
|
}
|
|
404
407
|
|
|
405
408
|
@media (forced-colors: active) {
|
|
409
|
+
[data-ui-choice-option].active {
|
|
410
|
+
outline: var(--ui-focus-width) solid Highlight;
|
|
411
|
+
outline-offset: calc(-1 * var(--ui-focus-width));
|
|
412
|
+
}
|
|
406
413
|
[data-ui-choice-option][aria-selected="true"]:not([aria-disabled="true"]):not(.active) {
|
|
407
414
|
outline: var(--ui-focus-width) solid Highlight;
|
|
408
415
|
outline-offset: calc(-1 * var(--ui-border-width));
|
package/vanilla/UiButton.js
CHANGED
|
@@ -15,11 +15,11 @@ const T8 = ["",[],4];
|
|
|
15
15
|
const T9 = ["",[]];
|
|
16
16
|
const T10 = ["",[]];
|
|
17
17
|
const T11 = ["",[],["ui-icon",["name","chevron-right","aria-hidden","true"]]];
|
|
18
|
-
const T12 = ["",[],"\n ",1,"\n ",4,"\n ",["span",["class","badge"],4],"\n "];
|
|
18
|
+
const T12 = ["",[],"\n ",1,"\n ",["span",["class","label"],4],"\n ",["span",["class","badge"],4],"\n "];
|
|
19
19
|
const T13 = ["span",["class","spinner-wrap"],["ui-spinner",["size","sm"]]];
|
|
20
20
|
const T14 = ["",[]];
|
|
21
21
|
const T15 = ["",[]];
|
|
22
|
-
const T16 = ["",[],"\n ",1,"\n ",4,"\n ",["span",["class","badge"],4],"\n "];
|
|
22
|
+
const T16 = ["",[],"\n ",1,"\n ",["span",["class","label"],4],"\n ",["span",["class","badge"],4],"\n "];
|
|
23
23
|
const T17 = ["span",["class","spinner-wrap"],["ui-spinner",["size","sm"]]];
|
|
24
24
|
const T18 = ["",[]];
|
|
25
25
|
const T19 = ["",[]];
|
|
@@ -373,8 +373,9 @@ export function createUiButton(options = {}, html) {
|
|
|
373
373
|
n.append((P12 ??= buildTemplate(T12)).cloneNode(true));
|
|
374
374
|
const t0 = n.firstChild.nextSibling;
|
|
375
375
|
const t1 = t0.nextSibling.nextSibling.nextSibling;
|
|
376
|
-
const t2 = t1.
|
|
377
|
-
const
|
|
376
|
+
const t2 = t1.firstChild;
|
|
377
|
+
const t3 = t1.nextSibling.nextSibling.firstChild;
|
|
378
|
+
const r = { n, v0: undefined, v1: undefined, v2: undefined, v3: undefined, v4: undefined, v5: undefined, v6: undefined, v7: undefined, v8: undefined, a1: t0, e0: t0.nextSibling, b0: undefined, a2: t2, e1: t2.nextSibling, b1: undefined, f1: undefined, a3: t3, e2: t3.nextSibling, b2: undefined, f2: undefined };
|
|
378
379
|
p12(r, -1, d);
|
|
379
380
|
return r;
|
|
380
381
|
};
|
|
@@ -436,19 +437,20 @@ export function createUiButton(options = {}, html) {
|
|
|
436
437
|
if (r.b0) { r.b0 = undefined; clearRegion(r.a1, r.e0); }
|
|
437
438
|
else { r.b0 = m13(d); r.e0.before(r.b0.n); }
|
|
438
439
|
} else if (r.b0 !== undefined) p13(r.b0, c, d);
|
|
439
|
-
if (r.f2 === undefined) { r.f2 = 1; const at = fillSlot(r.a3, r.e2, "badge", J, false, undefined, d);
|
|
440
|
-
if (Array.isArray(at)) (r.z ??= []).push(() => { at[0].l.delete(at[1]); dispose(at[1]); }); else if (at !== undefined) { r.b2 = m15(d); at.before(r.b2.n); } }
|
|
441
|
-
else if (r.b2 !== undefined) p15(r.b2, c, d);
|
|
442
440
|
if (r.f1 === undefined) { r.f1 = 1; const at = fillSlot(r.a2, r.e1, "", J, false, undefined, d);
|
|
443
441
|
if (Array.isArray(at)) (r.z ??= []).push(() => { at[0].l.delete(at[1]); dispose(at[1]); }); else if (at !== undefined) { r.b1 = m14(d); at.before(r.b1.n); } }
|
|
444
442
|
else if (r.b1 !== undefined) p14(r.b1, c, d);
|
|
443
|
+
if (r.f2 === undefined) { r.f2 = 1; const at = fillSlot(r.a3, r.e2, "badge", J, false, undefined, d);
|
|
444
|
+
if (Array.isArray(at)) (r.z ??= []).push(() => { at[0].l.delete(at[1]); dispose(at[1]); }); else if (at !== undefined) { r.b2 = m15(d); at.before(r.b2.n); } }
|
|
445
|
+
else if (r.b2 !== undefined) p15(r.b2, c, d);
|
|
445
446
|
};
|
|
446
447
|
const m16 = (n, d) => {
|
|
447
448
|
n.append((P16 ??= buildTemplate(T16)).cloneNode(true));
|
|
448
449
|
const t0 = n.firstChild.nextSibling;
|
|
449
450
|
const t1 = t0.nextSibling.nextSibling.nextSibling;
|
|
450
|
-
const t2 = t1.
|
|
451
|
-
const
|
|
451
|
+
const t2 = t1.firstChild;
|
|
452
|
+
const t3 = t1.nextSibling.nextSibling.firstChild;
|
|
453
|
+
const r = { n, v0: undefined, v1: undefined, v2: undefined, v3: undefined, v4: undefined, v5: undefined, v6: undefined, a1: t0, e0: t0.nextSibling, b0: undefined, a2: t2, e1: t2.nextSibling, b1: undefined, f1: undefined, a3: t3, e2: t3.nextSibling, b2: undefined, f2: undefined };
|
|
452
454
|
p16(r, -1, d);
|
|
453
455
|
return r;
|
|
454
456
|
};
|
|
@@ -496,12 +498,12 @@ export function createUiButton(options = {}, html) {
|
|
|
496
498
|
if (r.b0) { r.b0 = undefined; clearRegion(r.a1, r.e0); }
|
|
497
499
|
else { r.b0 = m17(d); r.e0.before(r.b0.n); }
|
|
498
500
|
} else if (r.b0 !== undefined) p17(r.b0, c, d);
|
|
499
|
-
if (r.f2 === undefined) { r.f2 = 1; const at = fillSlot(r.a3, r.e2, "badge", J, false, undefined, d);
|
|
500
|
-
if (Array.isArray(at)) (r.z ??= []).push(() => { at[0].l.delete(at[1]); dispose(at[1]); }); else if (at !== undefined) { r.b2 = m19(d); at.before(r.b2.n); } }
|
|
501
|
-
else if (r.b2 !== undefined) p19(r.b2, c, d);
|
|
502
501
|
if (r.f1 === undefined) { r.f1 = 1; const at = fillSlot(r.a2, r.e1, "", J, false, undefined, d);
|
|
503
502
|
if (Array.isArray(at)) (r.z ??= []).push(() => { at[0].l.delete(at[1]); dispose(at[1]); }); else if (at !== undefined) { r.b1 = m18(d); at.before(r.b1.n); } }
|
|
504
503
|
else if (r.b1 !== undefined) p18(r.b1, c, d);
|
|
504
|
+
if (r.f2 === undefined) { r.f2 = 1; const at = fillSlot(r.a3, r.e2, "badge", J, false, undefined, d);
|
|
505
|
+
if (Array.isArray(at)) (r.z ??= []).push(() => { at[0].l.delete(at[1]); dispose(at[1]); }); else if (at !== undefined) { r.b2 = m19(d); at.before(r.b2.n); } }
|
|
506
|
+
else if (r.b2 !== undefined) p19(r.b2, c, d);
|
|
505
507
|
};
|
|
506
508
|
const M = [m0, m6, m12, m16], N = [p0, p6, p12, p16];
|
|
507
509
|
let R;
|
package/vanilla/UiLightEditor.js
CHANGED
|
@@ -3,7 +3,7 @@ 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 ",["span",["class","source-glyph"],["ui-icon",["name","lightbulb"]]],"\n "],"\n "],"\n "],"\n ",["span",["class","coordinates"],"\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","hint"],"Drag or tap to move the light. Arrow keys adjust; Escape cancels."],"\n ",["ui-disclosure",["summary","Exact position"],["span",["class","coordinates","data-slotted","ui-light-editor"],"\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 "];
|
|
7
7
|
const T1 = ["",[]];
|
|
8
8
|
let P0, P1;
|
|
9
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"] };
|
|
@@ -86,7 +86,7 @@ export function createUiLightEditor(options = {}, html) {
|
|
|
86
86
|
const t2 = t1.firstChild.nextSibling.nextSibling.nextSibling;
|
|
87
87
|
const t3 = t2.firstChild;
|
|
88
88
|
const t4 = t2.nextSibling.nextSibling;
|
|
89
|
-
const t5 = t0.nextSibling.nextSibling;
|
|
89
|
+
const t5 = t0.nextSibling.nextSibling.nextSibling.nextSibling.firstChild;
|
|
90
90
|
const t6 = t5.firstChild.nextSibling;
|
|
91
91
|
const t7 = t6.nextSibling.nextSibling;
|
|
92
92
|
const R = { a0: t0, a3: t4, a4: t6, a5: t7, v0: null, v1: null, v2: null, v3: null, v4: null, v5: null, v6: null, v7: null, v8: null, a2: t3, e0: t3.nextSibling, b0: undefined, f0: undefined };
|
package/vue/UiButton.vue
CHANGED
|
@@ -904,10 +904,10 @@ useComponentHost(() => import('../components/ui-button/ui-button.js'), {
|
|
|
904
904
|
v-if="checkedProps.loading || checkedProps.pending"
|
|
905
905
|
class="spinner-wrap"
|
|
906
906
|
data-hn-ui-button
|
|
907
|
-
><UiSpinner class="ui-spinner" size="sm" /></span>{{ ' ' }}<
|
|
908
|
-
class="
|
|
907
|
+
><UiSpinner class="ui-spinner" size="sm" /></span>{{ ' ' }}<span
|
|
908
|
+
class="label"
|
|
909
909
|
data-hn-ui-button
|
|
910
|
-
><slot name="badge" /></span></a>
|
|
910
|
+
><slot /></span>{{ ' ' }}<span class="badge" data-hn-ui-button><slot name="badge" /></span></a>
|
|
911
911
|
<button
|
|
912
912
|
v-else
|
|
913
913
|
class="ui-button"
|
|
@@ -944,10 +944,10 @@ useComponentHost(() => import('../components/ui-button/ui-button.js'), {
|
|
|
944
944
|
v-if="checkedProps.loading || checkedProps.pending"
|
|
945
945
|
class="spinner-wrap"
|
|
946
946
|
data-hn-ui-button
|
|
947
|
-
><UiSpinner class="ui-spinner" size="sm" /></span>{{ ' ' }}<
|
|
948
|
-
class="
|
|
947
|
+
><UiSpinner class="ui-spinner" size="sm" /></span>{{ ' ' }}<span
|
|
948
|
+
class="label"
|
|
949
949
|
data-hn-ui-button
|
|
950
|
-
><slot name="badge" /></span>
|
|
950
|
+
><slot /></span>{{ ' ' }}<span class="badge" data-hn-ui-button><slot name="badge" /></span>
|
|
951
951
|
</button>
|
|
952
952
|
</template>
|
|
953
953
|
|
|
@@ -1031,6 +1031,8 @@ useComponentHost(() => import('../components/ui-button/ui-button.js'), {
|
|
|
1031
1031
|
/* A count is an adornment, not another line of label text. Keep the standard control height
|
|
1032
1032
|
with enough inset for a 24px mark; large content can still grow the button naturally. */
|
|
1033
1033
|
|
|
1034
|
+
/* Trim the text line itself: an anonymous flex item retains font-metric space in some fonts. */
|
|
1035
|
+
|
|
1034
1036
|
/* Short numeric and icon actions share a minimum box; large values remain readable. */
|
|
1035
1037
|
|
|
1036
1038
|
/* Card actions inherit Button's palette and behavior; only their shared layout changes.
|
|
@@ -1125,6 +1127,7 @@ useComponentHost(() => import('../components/ui-button/ui-button.js'), {
|
|
|
1125
1127
|
|
|
1126
1128
|
:global(:scope:where([data-hn-ui-button])) {
|
|
1127
1129
|
--_button-square-size: var(--ui-button-min-block-size, var(--ui-control-size-md));
|
|
1130
|
+
box-sizing: border-box !important;
|
|
1128
1131
|
appearance: none;
|
|
1129
1132
|
min-block-size: var(--ui-button-min-block-size, var(--ui-control-size-md));
|
|
1130
1133
|
border-style: solid;
|
|
@@ -1166,6 +1169,19 @@ useComponentHost(() => import('../components/ui-button/ui-button.js'), {
|
|
|
1166
1169
|
:global(:scope:not([data-appearance="link"]):has(.badge:not(:empty)):where([data-hn-ui-button])) {
|
|
1167
1170
|
padding-block: var(--ui-space-0-5) !important;
|
|
1168
1171
|
}
|
|
1172
|
+
:global(.label:where([data-hn-ui-button])) {
|
|
1173
|
+
display: block !important;
|
|
1174
|
+
align-content: center !important;
|
|
1175
|
+
min-inline-size: 0 !important;
|
|
1176
|
+
min-block-size: 1lh !important;
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
:global(.label:has(svg):where([data-hn-ui-button])) {
|
|
1180
|
+
display: inline-flex !important;
|
|
1181
|
+
align-items: center !important;
|
|
1182
|
+
gap: var(--ui-space-2) !important;
|
|
1183
|
+
text-box-trim: none;
|
|
1184
|
+
}
|
|
1169
1185
|
|
|
1170
1186
|
:global(.badge:where([data-hn-ui-button])) {
|
|
1171
1187
|
display: inline-flex !important;
|
|
@@ -1178,7 +1194,7 @@ useComponentHost(() => import('../components/ui-button/ui-button.js'), {
|
|
|
1178
1194
|
}
|
|
1179
1195
|
|
|
1180
1196
|
@supports (text-box-trim: trim-both) {
|
|
1181
|
-
:global(:
|
|
1197
|
+
:global(.label:not(:has(svg)):where([data-hn-ui-button])) {
|
|
1182
1198
|
text-box-trim: trim-both;
|
|
1183
1199
|
text-box-edge: cap alphabetic;
|
|
1184
1200
|
}
|
|
@@ -1499,6 +1515,11 @@ useComponentHost(() => import('../components/ui-button/ui-button.js'), {
|
|
|
1499
1515
|
text-decoration-color var(--ui-motion-fast) var(--ui-motion-ease);
|
|
1500
1516
|
}
|
|
1501
1517
|
|
|
1518
|
+
:global(:scope[data-appearance="link"] .label:where([data-hn-ui-button])) {
|
|
1519
|
+
display: inline !important;
|
|
1520
|
+
text-box-trim: none;
|
|
1521
|
+
}
|
|
1522
|
+
|
|
1502
1523
|
:global(:scope[data-appearance="link"]:hover:not(:disabled, [aria-disabled="true"]):where([data-hn-ui-button])) {
|
|
1503
1524
|
color: var(--ui-button-link-hover-text, var(--ui-text-primary));
|
|
1504
1525
|
text-decoration-color: currentColor;
|
package/vue/UiCheckbox.vue
CHANGED
|
@@ -377,20 +377,21 @@ useComponentHost(() => import('../components/ui-checkbox/ui-checkbox.js'), {
|
|
|
377
377
|
|
|
378
378
|
/* The label, and under it an optional line saying what the choice means. */
|
|
379
379
|
|
|
380
|
-
/*
|
|
380
|
+
/* The SVG's painted bounds are centred in its viewBox, including its round stroke.
|
|
381
|
+
Centre that box directly; rotated border boxes do not centre the visible check. */
|
|
381
382
|
|
|
382
383
|
@keyframes ui-checkbox-check {
|
|
383
384
|
from {
|
|
384
385
|
opacity: 0;
|
|
385
|
-
|
|
386
|
+
scale: 0.55;
|
|
386
387
|
}
|
|
387
388
|
65% {
|
|
388
389
|
opacity: 1;
|
|
389
|
-
|
|
390
|
+
scale: 1.12;
|
|
390
391
|
}
|
|
391
392
|
to {
|
|
392
393
|
opacity: 1;
|
|
393
|
-
|
|
394
|
+
scale: 1;
|
|
394
395
|
}
|
|
395
396
|
}
|
|
396
397
|
|
|
@@ -484,7 +485,8 @@ useComponentHost(() => import('../components/ui-checkbox/ui-checkbox.js'), {
|
|
|
484
485
|
|
|
485
486
|
:global(input:where([data-hn-ui-checkbox])::after) {
|
|
486
487
|
content: "";
|
|
487
|
-
position: absolute;
|
|
488
|
+
position: absolute !important;
|
|
489
|
+
transform: none !important;
|
|
488
490
|
opacity: 0;
|
|
489
491
|
transition: opacity var(--ui-motion-fast) var(--ui-motion-ease);
|
|
490
492
|
}
|
|
@@ -497,29 +499,28 @@ useComponentHost(() => import('../components/ui-checkbox/ui-checkbox.js'), {
|
|
|
497
499
|
box-shadow: var(--ui-control-inset);
|
|
498
500
|
}
|
|
499
501
|
:global(input:checked:where([data-hn-ui-checkbox])::after) {
|
|
500
|
-
inset:
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
border-style: solid;
|
|
507
|
-
border-color: var(--ui-text-on-accent);
|
|
508
|
-
border-width: 0 calc(var(--_ui-checkbox-size) * 0.125 / 1.125)
|
|
509
|
-
calc(var(--_ui-checkbox-size) * 0.125 / 1.125) 0;
|
|
502
|
+
inset: 50% auto auto 50% !important;
|
|
503
|
+
inline-size: calc(var(--_ui-checkbox-size) * 0.7) !important;
|
|
504
|
+
block-size: calc(var(--_ui-checkbox-size) * 0.7) !important;
|
|
505
|
+
background: var(--ui-text-on-accent);
|
|
506
|
+
mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 11.5 5 5 9-9'/%3E%3C/svg%3E")
|
|
507
|
+
center / contain no-repeat;
|
|
510
508
|
opacity: 1;
|
|
511
|
-
|
|
509
|
+
translate: -50% -50% !important;
|
|
512
510
|
animation: ui-checkbox-check var(--ui-motion-base)
|
|
513
511
|
var(--ui-motion-ease-out, cubic-bezier(0.16, 1, 0.3, 1)) both;
|
|
514
512
|
}
|
|
515
513
|
|
|
516
514
|
:global(input:indeterminate:where([data-hn-ui-checkbox])::after) {
|
|
517
|
-
|
|
518
|
-
|
|
515
|
+
mask: none;
|
|
516
|
+
animation: none;
|
|
517
|
+
inset: 50% calc(var(--_ui-checkbox-size) * 0.23 / 1.125) auto !important;
|
|
518
|
+
inline-size: auto !important;
|
|
519
|
+
block-size: calc(var(--_ui-checkbox-size) * 0.125 / 1.125) !important;
|
|
519
520
|
border-radius: var(--ui-radius-round);
|
|
520
521
|
background: var(--ui-text-on-accent);
|
|
521
522
|
opacity: 1;
|
|
522
|
-
|
|
523
|
+
translate: 0 -50% !important;
|
|
523
524
|
}
|
|
524
525
|
|
|
525
526
|
@media (prefers-reduced-motion: reduce) {
|
|
@@ -529,6 +530,20 @@ useComponentHost(() => import('../components/ui-checkbox/ui-checkbox.js'), {
|
|
|
529
530
|
}
|
|
530
531
|
}
|
|
531
532
|
|
|
533
|
+
@media (forced-colors: active) {
|
|
534
|
+
:global(input:checked:where([data-hn-ui-checkbox])),
|
|
535
|
+
:global(input:indeterminate:where([data-hn-ui-checkbox])) {
|
|
536
|
+
forced-color-adjust: none;
|
|
537
|
+
background: Highlight;
|
|
538
|
+
border-color: Highlight;
|
|
539
|
+
}
|
|
540
|
+
:global(input:checked:where([data-hn-ui-checkbox])::after),
|
|
541
|
+
:global(input:indeterminate:where([data-hn-ui-checkbox])::after) {
|
|
542
|
+
forced-color-adjust: none;
|
|
543
|
+
background: HighlightText;
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
|
|
532
547
|
:global(input:hover:enabled:where([data-hn-ui-checkbox])) {
|
|
533
548
|
border-color: var(--ui-accent-solid);
|
|
534
549
|
}
|