@motion-proto/live-tokens 0.30.0 → 0.32.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.
- package/.claude/skills/live-tokens-create-component/SKILL.md +1 -0
- package/dist-plugin/{chunk-2TW77U3O.js → chunk-MJO4T3CM.js} +88 -1
- package/dist-plugin/index.cjs +88 -1
- package/dist-plugin/index.js +1 -1
- package/dist-plugin/tokensCssMigrations/index.cjs +88 -1
- package/dist-plugin/tokensCssMigrations/index.js +1 -1
- package/package.json +3 -2
- package/src/editor/component-editor/ImageEditor.svelte +37 -11
- package/src/editor/component-editor/ImageLightboxEditor.svelte +27 -3
- package/src/editor/ui/VariablesTab.svelte +6 -1
- package/src/editor/ui/sections/tokenScales.ts +4 -0
- package/src/system/components/Dialog.svelte +4 -1
- package/src/system/components/Image.svelte +36 -5
- package/src/system/components/ImageLightbox.svelte +500 -153
- package/src/system/internal/portal.ts +18 -0
- package/src/system/styles/tokens.css +0 -9
|
@@ -106,6 +106,7 @@ The authoritative recognised list lives in `bin/check-component.mjs` (`KNOWN_SUF
|
|
|
106
106
|
|
|
107
107
|
### Rules that bite
|
|
108
108
|
|
|
109
|
+
- **Fixed overlays must portal to `<body>`.** Any `position: fixed` layer (modal, lightbox, full-screen backdrop) is trapped — clipped or painted under other chrome — by a transformed / `isolation` / `contain` / `will-change` ancestor, which real consumer pages (and the editor's own preview pane) commonly have. Render the fixed layer with `use:portal` from `src/system/internal/portal.ts` so it escapes to `<body>`; pass `use:portal={enabled}` to keep an in-flow preview variant in place (see `Dialog`). `check:overlay-portal` fails the build if a component has `position: fixed` without it. Anchored popovers (`position: absolute` relative to a trigger, like `Tooltip`) are exempt. Two consequences of moving to `<body>`: DOM events from the layer no longer bubble to a consumer ancestor (use component callbacks, as `Dialog` does), and a subtree-scoped CSS-variable theme no longer reaches it (this library themes via `:root`, so fine here). If the layer is a modal, also give it `role="dialog"` + `aria-modal`, move focus in on open and restore it on close, and trap `Tab` (see `ImageLightbox`).
|
|
109
110
|
- **State before property.** `--mywidget-button-hover-surface` ✓ — `--mywidget-button-surface-hover` ✗ (breaks sibling matching).
|
|
110
111
|
- **Defaults reference theme tokens, never raw values.** `var(--surface-primary)` ✓ — `#6a4ce8` ✗.
|
|
111
112
|
- **No abbreviations.** `bg` → `surface`; `fg` → `text`; component ids are never abbreviated.
|
|
@@ -173,6 +173,91 @@ var tokensCssMigration_2026_06_03_transformScaleAdditions = {
|
|
|
173
173
|
}
|
|
174
174
|
};
|
|
175
175
|
|
|
176
|
+
// vite-plugin/tokensCssMigrations/migrations/2026-06-04-remove-dead-size-icon-scale.ts
|
|
177
|
+
var tokensCssMigration_2026_06_04_removeDeadSizeIconScale = {
|
|
178
|
+
id: "2026-06-04-remove-dead-size-icon-scale",
|
|
179
|
+
description: "Remove the unused --size-icon-* scale (live scale is --icon-size-*)",
|
|
180
|
+
apply(css) {
|
|
181
|
+
return removeTokensMatching(css, (name) => name.startsWith("--size-icon-"));
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
// vite-plugin/tokensCssMigrations/migrations/2026-06-04-easing-color-and-typescale-additions.ts
|
|
186
|
+
var tokensCssMigration_2026_06_04_easingColorAndTypescaleAdditions = {
|
|
187
|
+
id: "2026-06-04-easing-color-and-typescale-additions",
|
|
188
|
+
description: "Add the full --ease-* scale, --color-white/black, and --font-size-7xl",
|
|
189
|
+
apply(css) {
|
|
190
|
+
let out = css;
|
|
191
|
+
out = ensureScale(out, {
|
|
192
|
+
anchorPrefixes: ["--ease-", "--transition-", "--duration-"],
|
|
193
|
+
entries: [
|
|
194
|
+
{ name: "--ease-linear", value: "linear" },
|
|
195
|
+
{ name: "--ease-in-sine", value: "cubic-bezier(0.12, 0, 0.39, 0)" },
|
|
196
|
+
{ name: "--ease-out-sine", value: "cubic-bezier(0.61, 1, 0.88, 1)" },
|
|
197
|
+
{ name: "--ease-in-out-sine", value: "cubic-bezier(0.37, 0, 0.63, 1)" },
|
|
198
|
+
{ name: "--ease-in-quad", value: "cubic-bezier(0.11, 0, 0.5, 0)" },
|
|
199
|
+
{ name: "--ease-out-quad", value: "cubic-bezier(0.5, 1, 0.89, 1)" },
|
|
200
|
+
{ name: "--ease-in-out-quad", value: "cubic-bezier(0.45, 0, 0.55, 1)" },
|
|
201
|
+
{ name: "--ease-in-cubic", value: "cubic-bezier(0.32, 0, 0.67, 0)" },
|
|
202
|
+
{ name: "--ease-out-cubic", value: "cubic-bezier(0.33, 1, 0.68, 1)" },
|
|
203
|
+
{ name: "--ease-in-out-cubic", value: "cubic-bezier(0.65, 0, 0.35, 1)" },
|
|
204
|
+
{ name: "--ease-in-quart", value: "cubic-bezier(0.5, 0, 0.75, 0)" },
|
|
205
|
+
{ name: "--ease-out-quart", value: "cubic-bezier(0.25, 1, 0.5, 1)" },
|
|
206
|
+
{ name: "--ease-in-out-quart", value: "cubic-bezier(0.76, 0, 0.24, 1)" },
|
|
207
|
+
{ name: "--ease-in-quint", value: "cubic-bezier(0.64, 0, 0.78, 0)" },
|
|
208
|
+
{ name: "--ease-out-quint", value: "cubic-bezier(0.22, 1, 0.36, 1)" },
|
|
209
|
+
{ name: "--ease-in-out-quint", value: "cubic-bezier(0.83, 0, 0.17, 1)" },
|
|
210
|
+
{ name: "--ease-in-expo", value: "cubic-bezier(0.7, 0, 0.84, 0)" },
|
|
211
|
+
{ name: "--ease-out-expo", value: "cubic-bezier(0.16, 1, 0.3, 1)" },
|
|
212
|
+
{ name: "--ease-in-out-expo", value: "cubic-bezier(0.87, 0, 0.13, 1)" },
|
|
213
|
+
{ name: "--ease-in-circ", value: "cubic-bezier(0.55, 0, 1, 0.45)" },
|
|
214
|
+
{ name: "--ease-out-circ", value: "cubic-bezier(0, 0.55, 0.45, 1)" },
|
|
215
|
+
{ name: "--ease-in-out-circ", value: "cubic-bezier(0.85, 0, 0.15, 1)" },
|
|
216
|
+
{ name: "--ease-in-back", value: "cubic-bezier(0.36, 0, 0.66, -0.56)" },
|
|
217
|
+
{ name: "--ease-out-back", value: "cubic-bezier(0.34, 1.56, 0.64, 1)" },
|
|
218
|
+
{ name: "--ease-in-out-back", value: "cubic-bezier(0.68, -0.6, 0.32, 1.6)" },
|
|
219
|
+
{
|
|
220
|
+
name: "--ease-in-elastic",
|
|
221
|
+
value: "linear(0, 0.0007 8.1%, 0.0019 12.1%, 0.0027 13.7%, 0.0046 15.7%, -0.0046 18.7%, -0.0202 22.1%, -0.0234 23.6%, -0.0224 24.9%, -0.0156 26.7%, 0.0091 29.4%, 0.0666 33.4%, 0.0848 34.9%, 0.0916 36.4%, 0.0837 38.1%, 0.0581 40.1%, -0.0204 43.7%, -0.221 51.3%, -0.2825 53.6%, -0.317 55.4%, -0.3253 57.1%, -0.3071 58.8%, -0.2554 60.9%, -0.1295 63.7%, 0.4515 73.1%, 0.7257 78.4%, 0.834 81.2%, 0.9221 84.1%, 0.9817 87.1%, 1.0144 90.4%, 1.026 94.6%, 1)"
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
name: "--ease-out-elastic",
|
|
225
|
+
value: "linear(0, 0.974 4.6%, 1.026 5.4%, 1.018 6.9%, 0.952 12.9%, 0.876 15.9%, 0.751 18.8%, 0.557 22.4%, -0.451 36.3%, -0.722 42.9%, -0.832 46.6%, -0.918 51.3%, -0.916 54.8%, -0.832 59.4%, -0.665 64.6%, 0.221 78%, 0.317 81.2%, 0.317 84.4%, 0.281 87.6%, 0.232 91.1%, 0.058 100%)"
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
name: "--ease-in-out-elastic",
|
|
229
|
+
value: "linear(0, 0.0001 7.7%, -0.0048 12.7%, -0.0064 14.6%, -0.0064 16.5%, -0.0026 18.5%, 0.0179 21.4%, 0.0617 24.1%, 0.0617 26.5%, 0.0309 29%, -0.0589 32.7%, -0.3 38.1%, -0.4307 40.6%, -0.4844 43%, -0.4844 48%, -0.4307 50.4%, -0.3 52.9%, 0.3 60.5%, 0.4307 63%, 0.4844 65.4%, 0.4844 70.4%, 0.4307 72.8%, 0.3 75.3%, 0.0589 80.7%, -0.0309 84.4%, -0.0617 86.9%, -0.0617 89.3%, -0.0179 92%, 0.0026 94.9%, 0.0064 96.8%, 0.0064 98.7%, 0.0048 100%, 1)"
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
name: "--ease-in-bounce",
|
|
233
|
+
value: "linear(0, 0.005, 0.018, 0.039, 0.069, 0.108, 0.156, 0.213, 0.281, 0.36, 0.451, 0.555, 0.674, 0.81, 0.967, 0.881, 0.838, 0.838, 0.881, 0.97, 0.952, 0.95, 0.969, 0.999, 0.984, 0.982, 0.989, 1)"
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
name: "--ease-out-bounce",
|
|
237
|
+
value: "linear(0, 0.011, 0.031, 0.018, 0.05, 0.151, 0.301, 0.5, 0.747, 0.945, 0.997, 1, 0.969, 0.954, 0.969, 0.952, 0.952, 0.969, 1, 0.984, 0.982, 0.984, 0.997, 0.984, 0.989, 1)"
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
name: "--ease-in-out-bounce",
|
|
241
|
+
value: "linear(0, 0.003, 0.009, 0.019, 0.034, 0.054, 0.078, 0.107, 0.141, 0.18, 0.226, 0.278, 0.337, 0.405, 0.483, 0.471, 0.42, 0.419, 0.46, 0.494, 0.5, 0.506, 0.54, 0.581, 0.58, 0.529, 0.517, 0.595, 0.663, 0.722, 0.774, 0.819, 0.859, 0.893, 0.922, 0.946, 0.966, 0.981, 0.991, 0.997, 1)"
|
|
242
|
+
}
|
|
243
|
+
]
|
|
244
|
+
});
|
|
245
|
+
out = ensureScale(out, {
|
|
246
|
+
sectionComment: "Invariants \u2014 never themed, not part of any ramp.",
|
|
247
|
+
anchorPrefixes: ["--color-"],
|
|
248
|
+
entries: [
|
|
249
|
+
{ name: "--color-white", value: "#ffffff" },
|
|
250
|
+
{ name: "--color-black", value: "#000000" }
|
|
251
|
+
]
|
|
252
|
+
});
|
|
253
|
+
out = ensureScale(out, {
|
|
254
|
+
anchorPrefixes: ["--font-size-", "--font-"],
|
|
255
|
+
entries: [{ name: "--font-size-7xl", value: "4.5rem" }]
|
|
256
|
+
});
|
|
257
|
+
return out;
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
|
|
176
261
|
// vite-plugin/files/dataPaths.ts
|
|
177
262
|
import fs from "fs";
|
|
178
263
|
import path from "path";
|
|
@@ -223,7 +308,9 @@ function resolveDataDirs(opts = {}) {
|
|
|
223
308
|
var TOKENS_CSS_MIGRATIONS = [
|
|
224
309
|
tokensCssMigration_2026_05_29_typographyScaleAdditions,
|
|
225
310
|
tokensCssMigration_2026_05_29_sectiondividerLegacyAxisCleanup,
|
|
226
|
-
tokensCssMigration_2026_06_03_transformScaleAdditions
|
|
311
|
+
tokensCssMigration_2026_06_03_transformScaleAdditions,
|
|
312
|
+
tokensCssMigration_2026_06_04_removeDeadSizeIconScale,
|
|
313
|
+
tokensCssMigration_2026_06_04_easingColorAndTypescaleAdditions
|
|
227
314
|
];
|
|
228
315
|
function runTokensCssMigrations(css) {
|
|
229
316
|
let out = css;
|
package/dist-plugin/index.cjs
CHANGED
|
@@ -797,11 +797,98 @@ var tokensCssMigration_2026_06_03_transformScaleAdditions = {
|
|
|
797
797
|
}
|
|
798
798
|
};
|
|
799
799
|
|
|
800
|
+
// vite-plugin/tokensCssMigrations/migrations/2026-06-04-remove-dead-size-icon-scale.ts
|
|
801
|
+
var tokensCssMigration_2026_06_04_removeDeadSizeIconScale = {
|
|
802
|
+
id: "2026-06-04-remove-dead-size-icon-scale",
|
|
803
|
+
description: "Remove the unused --size-icon-* scale (live scale is --icon-size-*)",
|
|
804
|
+
apply(css) {
|
|
805
|
+
return removeTokensMatching(css, (name) => name.startsWith("--size-icon-"));
|
|
806
|
+
}
|
|
807
|
+
};
|
|
808
|
+
|
|
809
|
+
// vite-plugin/tokensCssMigrations/migrations/2026-06-04-easing-color-and-typescale-additions.ts
|
|
810
|
+
var tokensCssMigration_2026_06_04_easingColorAndTypescaleAdditions = {
|
|
811
|
+
id: "2026-06-04-easing-color-and-typescale-additions",
|
|
812
|
+
description: "Add the full --ease-* scale, --color-white/black, and --font-size-7xl",
|
|
813
|
+
apply(css) {
|
|
814
|
+
let out = css;
|
|
815
|
+
out = ensureScale(out, {
|
|
816
|
+
anchorPrefixes: ["--ease-", "--transition-", "--duration-"],
|
|
817
|
+
entries: [
|
|
818
|
+
{ name: "--ease-linear", value: "linear" },
|
|
819
|
+
{ name: "--ease-in-sine", value: "cubic-bezier(0.12, 0, 0.39, 0)" },
|
|
820
|
+
{ name: "--ease-out-sine", value: "cubic-bezier(0.61, 1, 0.88, 1)" },
|
|
821
|
+
{ name: "--ease-in-out-sine", value: "cubic-bezier(0.37, 0, 0.63, 1)" },
|
|
822
|
+
{ name: "--ease-in-quad", value: "cubic-bezier(0.11, 0, 0.5, 0)" },
|
|
823
|
+
{ name: "--ease-out-quad", value: "cubic-bezier(0.5, 1, 0.89, 1)" },
|
|
824
|
+
{ name: "--ease-in-out-quad", value: "cubic-bezier(0.45, 0, 0.55, 1)" },
|
|
825
|
+
{ name: "--ease-in-cubic", value: "cubic-bezier(0.32, 0, 0.67, 0)" },
|
|
826
|
+
{ name: "--ease-out-cubic", value: "cubic-bezier(0.33, 1, 0.68, 1)" },
|
|
827
|
+
{ name: "--ease-in-out-cubic", value: "cubic-bezier(0.65, 0, 0.35, 1)" },
|
|
828
|
+
{ name: "--ease-in-quart", value: "cubic-bezier(0.5, 0, 0.75, 0)" },
|
|
829
|
+
{ name: "--ease-out-quart", value: "cubic-bezier(0.25, 1, 0.5, 1)" },
|
|
830
|
+
{ name: "--ease-in-out-quart", value: "cubic-bezier(0.76, 0, 0.24, 1)" },
|
|
831
|
+
{ name: "--ease-in-quint", value: "cubic-bezier(0.64, 0, 0.78, 0)" },
|
|
832
|
+
{ name: "--ease-out-quint", value: "cubic-bezier(0.22, 1, 0.36, 1)" },
|
|
833
|
+
{ name: "--ease-in-out-quint", value: "cubic-bezier(0.83, 0, 0.17, 1)" },
|
|
834
|
+
{ name: "--ease-in-expo", value: "cubic-bezier(0.7, 0, 0.84, 0)" },
|
|
835
|
+
{ name: "--ease-out-expo", value: "cubic-bezier(0.16, 1, 0.3, 1)" },
|
|
836
|
+
{ name: "--ease-in-out-expo", value: "cubic-bezier(0.87, 0, 0.13, 1)" },
|
|
837
|
+
{ name: "--ease-in-circ", value: "cubic-bezier(0.55, 0, 1, 0.45)" },
|
|
838
|
+
{ name: "--ease-out-circ", value: "cubic-bezier(0, 0.55, 0.45, 1)" },
|
|
839
|
+
{ name: "--ease-in-out-circ", value: "cubic-bezier(0.85, 0, 0.15, 1)" },
|
|
840
|
+
{ name: "--ease-in-back", value: "cubic-bezier(0.36, 0, 0.66, -0.56)" },
|
|
841
|
+
{ name: "--ease-out-back", value: "cubic-bezier(0.34, 1.56, 0.64, 1)" },
|
|
842
|
+
{ name: "--ease-in-out-back", value: "cubic-bezier(0.68, -0.6, 0.32, 1.6)" },
|
|
843
|
+
{
|
|
844
|
+
name: "--ease-in-elastic",
|
|
845
|
+
value: "linear(0, 0.0007 8.1%, 0.0019 12.1%, 0.0027 13.7%, 0.0046 15.7%, -0.0046 18.7%, -0.0202 22.1%, -0.0234 23.6%, -0.0224 24.9%, -0.0156 26.7%, 0.0091 29.4%, 0.0666 33.4%, 0.0848 34.9%, 0.0916 36.4%, 0.0837 38.1%, 0.0581 40.1%, -0.0204 43.7%, -0.221 51.3%, -0.2825 53.6%, -0.317 55.4%, -0.3253 57.1%, -0.3071 58.8%, -0.2554 60.9%, -0.1295 63.7%, 0.4515 73.1%, 0.7257 78.4%, 0.834 81.2%, 0.9221 84.1%, 0.9817 87.1%, 1.0144 90.4%, 1.026 94.6%, 1)"
|
|
846
|
+
},
|
|
847
|
+
{
|
|
848
|
+
name: "--ease-out-elastic",
|
|
849
|
+
value: "linear(0, 0.974 4.6%, 1.026 5.4%, 1.018 6.9%, 0.952 12.9%, 0.876 15.9%, 0.751 18.8%, 0.557 22.4%, -0.451 36.3%, -0.722 42.9%, -0.832 46.6%, -0.918 51.3%, -0.916 54.8%, -0.832 59.4%, -0.665 64.6%, 0.221 78%, 0.317 81.2%, 0.317 84.4%, 0.281 87.6%, 0.232 91.1%, 0.058 100%)"
|
|
850
|
+
},
|
|
851
|
+
{
|
|
852
|
+
name: "--ease-in-out-elastic",
|
|
853
|
+
value: "linear(0, 0.0001 7.7%, -0.0048 12.7%, -0.0064 14.6%, -0.0064 16.5%, -0.0026 18.5%, 0.0179 21.4%, 0.0617 24.1%, 0.0617 26.5%, 0.0309 29%, -0.0589 32.7%, -0.3 38.1%, -0.4307 40.6%, -0.4844 43%, -0.4844 48%, -0.4307 50.4%, -0.3 52.9%, 0.3 60.5%, 0.4307 63%, 0.4844 65.4%, 0.4844 70.4%, 0.4307 72.8%, 0.3 75.3%, 0.0589 80.7%, -0.0309 84.4%, -0.0617 86.9%, -0.0617 89.3%, -0.0179 92%, 0.0026 94.9%, 0.0064 96.8%, 0.0064 98.7%, 0.0048 100%, 1)"
|
|
854
|
+
},
|
|
855
|
+
{
|
|
856
|
+
name: "--ease-in-bounce",
|
|
857
|
+
value: "linear(0, 0.005, 0.018, 0.039, 0.069, 0.108, 0.156, 0.213, 0.281, 0.36, 0.451, 0.555, 0.674, 0.81, 0.967, 0.881, 0.838, 0.838, 0.881, 0.97, 0.952, 0.95, 0.969, 0.999, 0.984, 0.982, 0.989, 1)"
|
|
858
|
+
},
|
|
859
|
+
{
|
|
860
|
+
name: "--ease-out-bounce",
|
|
861
|
+
value: "linear(0, 0.011, 0.031, 0.018, 0.05, 0.151, 0.301, 0.5, 0.747, 0.945, 0.997, 1, 0.969, 0.954, 0.969, 0.952, 0.952, 0.969, 1, 0.984, 0.982, 0.984, 0.997, 0.984, 0.989, 1)"
|
|
862
|
+
},
|
|
863
|
+
{
|
|
864
|
+
name: "--ease-in-out-bounce",
|
|
865
|
+
value: "linear(0, 0.003, 0.009, 0.019, 0.034, 0.054, 0.078, 0.107, 0.141, 0.18, 0.226, 0.278, 0.337, 0.405, 0.483, 0.471, 0.42, 0.419, 0.46, 0.494, 0.5, 0.506, 0.54, 0.581, 0.58, 0.529, 0.517, 0.595, 0.663, 0.722, 0.774, 0.819, 0.859, 0.893, 0.922, 0.946, 0.966, 0.981, 0.991, 0.997, 1)"
|
|
866
|
+
}
|
|
867
|
+
]
|
|
868
|
+
});
|
|
869
|
+
out = ensureScale(out, {
|
|
870
|
+
sectionComment: "Invariants \u2014 never themed, not part of any ramp.",
|
|
871
|
+
anchorPrefixes: ["--color-"],
|
|
872
|
+
entries: [
|
|
873
|
+
{ name: "--color-white", value: "#ffffff" },
|
|
874
|
+
{ name: "--color-black", value: "#000000" }
|
|
875
|
+
]
|
|
876
|
+
});
|
|
877
|
+
out = ensureScale(out, {
|
|
878
|
+
anchorPrefixes: ["--font-size-", "--font-"],
|
|
879
|
+
entries: [{ name: "--font-size-7xl", value: "4.5rem" }]
|
|
880
|
+
});
|
|
881
|
+
return out;
|
|
882
|
+
}
|
|
883
|
+
};
|
|
884
|
+
|
|
800
885
|
// vite-plugin/tokensCssMigrations/index.ts
|
|
801
886
|
var TOKENS_CSS_MIGRATIONS = [
|
|
802
887
|
tokensCssMigration_2026_05_29_typographyScaleAdditions,
|
|
803
888
|
tokensCssMigration_2026_05_29_sectiondividerLegacyAxisCleanup,
|
|
804
|
-
tokensCssMigration_2026_06_03_transformScaleAdditions
|
|
889
|
+
tokensCssMigration_2026_06_03_transformScaleAdditions,
|
|
890
|
+
tokensCssMigration_2026_06_04_removeDeadSizeIconScale,
|
|
891
|
+
tokensCssMigration_2026_06_04_easingColorAndTypescaleAdditions
|
|
805
892
|
];
|
|
806
893
|
function runTokensCssMigrations(css) {
|
|
807
894
|
let out = css;
|
package/dist-plugin/index.js
CHANGED
|
@@ -218,6 +218,91 @@ var tokensCssMigration_2026_06_03_transformScaleAdditions = {
|
|
|
218
218
|
}
|
|
219
219
|
};
|
|
220
220
|
|
|
221
|
+
// vite-plugin/tokensCssMigrations/migrations/2026-06-04-remove-dead-size-icon-scale.ts
|
|
222
|
+
var tokensCssMigration_2026_06_04_removeDeadSizeIconScale = {
|
|
223
|
+
id: "2026-06-04-remove-dead-size-icon-scale",
|
|
224
|
+
description: "Remove the unused --size-icon-* scale (live scale is --icon-size-*)",
|
|
225
|
+
apply(css) {
|
|
226
|
+
return removeTokensMatching(css, (name) => name.startsWith("--size-icon-"));
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
// vite-plugin/tokensCssMigrations/migrations/2026-06-04-easing-color-and-typescale-additions.ts
|
|
231
|
+
var tokensCssMigration_2026_06_04_easingColorAndTypescaleAdditions = {
|
|
232
|
+
id: "2026-06-04-easing-color-and-typescale-additions",
|
|
233
|
+
description: "Add the full --ease-* scale, --color-white/black, and --font-size-7xl",
|
|
234
|
+
apply(css) {
|
|
235
|
+
let out = css;
|
|
236
|
+
out = ensureScale(out, {
|
|
237
|
+
anchorPrefixes: ["--ease-", "--transition-", "--duration-"],
|
|
238
|
+
entries: [
|
|
239
|
+
{ name: "--ease-linear", value: "linear" },
|
|
240
|
+
{ name: "--ease-in-sine", value: "cubic-bezier(0.12, 0, 0.39, 0)" },
|
|
241
|
+
{ name: "--ease-out-sine", value: "cubic-bezier(0.61, 1, 0.88, 1)" },
|
|
242
|
+
{ name: "--ease-in-out-sine", value: "cubic-bezier(0.37, 0, 0.63, 1)" },
|
|
243
|
+
{ name: "--ease-in-quad", value: "cubic-bezier(0.11, 0, 0.5, 0)" },
|
|
244
|
+
{ name: "--ease-out-quad", value: "cubic-bezier(0.5, 1, 0.89, 1)" },
|
|
245
|
+
{ name: "--ease-in-out-quad", value: "cubic-bezier(0.45, 0, 0.55, 1)" },
|
|
246
|
+
{ name: "--ease-in-cubic", value: "cubic-bezier(0.32, 0, 0.67, 0)" },
|
|
247
|
+
{ name: "--ease-out-cubic", value: "cubic-bezier(0.33, 1, 0.68, 1)" },
|
|
248
|
+
{ name: "--ease-in-out-cubic", value: "cubic-bezier(0.65, 0, 0.35, 1)" },
|
|
249
|
+
{ name: "--ease-in-quart", value: "cubic-bezier(0.5, 0, 0.75, 0)" },
|
|
250
|
+
{ name: "--ease-out-quart", value: "cubic-bezier(0.25, 1, 0.5, 1)" },
|
|
251
|
+
{ name: "--ease-in-out-quart", value: "cubic-bezier(0.76, 0, 0.24, 1)" },
|
|
252
|
+
{ name: "--ease-in-quint", value: "cubic-bezier(0.64, 0, 0.78, 0)" },
|
|
253
|
+
{ name: "--ease-out-quint", value: "cubic-bezier(0.22, 1, 0.36, 1)" },
|
|
254
|
+
{ name: "--ease-in-out-quint", value: "cubic-bezier(0.83, 0, 0.17, 1)" },
|
|
255
|
+
{ name: "--ease-in-expo", value: "cubic-bezier(0.7, 0, 0.84, 0)" },
|
|
256
|
+
{ name: "--ease-out-expo", value: "cubic-bezier(0.16, 1, 0.3, 1)" },
|
|
257
|
+
{ name: "--ease-in-out-expo", value: "cubic-bezier(0.87, 0, 0.13, 1)" },
|
|
258
|
+
{ name: "--ease-in-circ", value: "cubic-bezier(0.55, 0, 1, 0.45)" },
|
|
259
|
+
{ name: "--ease-out-circ", value: "cubic-bezier(0, 0.55, 0.45, 1)" },
|
|
260
|
+
{ name: "--ease-in-out-circ", value: "cubic-bezier(0.85, 0, 0.15, 1)" },
|
|
261
|
+
{ name: "--ease-in-back", value: "cubic-bezier(0.36, 0, 0.66, -0.56)" },
|
|
262
|
+
{ name: "--ease-out-back", value: "cubic-bezier(0.34, 1.56, 0.64, 1)" },
|
|
263
|
+
{ name: "--ease-in-out-back", value: "cubic-bezier(0.68, -0.6, 0.32, 1.6)" },
|
|
264
|
+
{
|
|
265
|
+
name: "--ease-in-elastic",
|
|
266
|
+
value: "linear(0, 0.0007 8.1%, 0.0019 12.1%, 0.0027 13.7%, 0.0046 15.7%, -0.0046 18.7%, -0.0202 22.1%, -0.0234 23.6%, -0.0224 24.9%, -0.0156 26.7%, 0.0091 29.4%, 0.0666 33.4%, 0.0848 34.9%, 0.0916 36.4%, 0.0837 38.1%, 0.0581 40.1%, -0.0204 43.7%, -0.221 51.3%, -0.2825 53.6%, -0.317 55.4%, -0.3253 57.1%, -0.3071 58.8%, -0.2554 60.9%, -0.1295 63.7%, 0.4515 73.1%, 0.7257 78.4%, 0.834 81.2%, 0.9221 84.1%, 0.9817 87.1%, 1.0144 90.4%, 1.026 94.6%, 1)"
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
name: "--ease-out-elastic",
|
|
270
|
+
value: "linear(0, 0.974 4.6%, 1.026 5.4%, 1.018 6.9%, 0.952 12.9%, 0.876 15.9%, 0.751 18.8%, 0.557 22.4%, -0.451 36.3%, -0.722 42.9%, -0.832 46.6%, -0.918 51.3%, -0.916 54.8%, -0.832 59.4%, -0.665 64.6%, 0.221 78%, 0.317 81.2%, 0.317 84.4%, 0.281 87.6%, 0.232 91.1%, 0.058 100%)"
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
name: "--ease-in-out-elastic",
|
|
274
|
+
value: "linear(0, 0.0001 7.7%, -0.0048 12.7%, -0.0064 14.6%, -0.0064 16.5%, -0.0026 18.5%, 0.0179 21.4%, 0.0617 24.1%, 0.0617 26.5%, 0.0309 29%, -0.0589 32.7%, -0.3 38.1%, -0.4307 40.6%, -0.4844 43%, -0.4844 48%, -0.4307 50.4%, -0.3 52.9%, 0.3 60.5%, 0.4307 63%, 0.4844 65.4%, 0.4844 70.4%, 0.4307 72.8%, 0.3 75.3%, 0.0589 80.7%, -0.0309 84.4%, -0.0617 86.9%, -0.0617 89.3%, -0.0179 92%, 0.0026 94.9%, 0.0064 96.8%, 0.0064 98.7%, 0.0048 100%, 1)"
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
name: "--ease-in-bounce",
|
|
278
|
+
value: "linear(0, 0.005, 0.018, 0.039, 0.069, 0.108, 0.156, 0.213, 0.281, 0.36, 0.451, 0.555, 0.674, 0.81, 0.967, 0.881, 0.838, 0.838, 0.881, 0.97, 0.952, 0.95, 0.969, 0.999, 0.984, 0.982, 0.989, 1)"
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
name: "--ease-out-bounce",
|
|
282
|
+
value: "linear(0, 0.011, 0.031, 0.018, 0.05, 0.151, 0.301, 0.5, 0.747, 0.945, 0.997, 1, 0.969, 0.954, 0.969, 0.952, 0.952, 0.969, 1, 0.984, 0.982, 0.984, 0.997, 0.984, 0.989, 1)"
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
name: "--ease-in-out-bounce",
|
|
286
|
+
value: "linear(0, 0.003, 0.009, 0.019, 0.034, 0.054, 0.078, 0.107, 0.141, 0.18, 0.226, 0.278, 0.337, 0.405, 0.483, 0.471, 0.42, 0.419, 0.46, 0.494, 0.5, 0.506, 0.54, 0.581, 0.58, 0.529, 0.517, 0.595, 0.663, 0.722, 0.774, 0.819, 0.859, 0.893, 0.922, 0.946, 0.966, 0.981, 0.991, 0.997, 1)"
|
|
287
|
+
}
|
|
288
|
+
]
|
|
289
|
+
});
|
|
290
|
+
out = ensureScale(out, {
|
|
291
|
+
sectionComment: "Invariants \u2014 never themed, not part of any ramp.",
|
|
292
|
+
anchorPrefixes: ["--color-"],
|
|
293
|
+
entries: [
|
|
294
|
+
{ name: "--color-white", value: "#ffffff" },
|
|
295
|
+
{ name: "--color-black", value: "#000000" }
|
|
296
|
+
]
|
|
297
|
+
});
|
|
298
|
+
out = ensureScale(out, {
|
|
299
|
+
anchorPrefixes: ["--font-size-", "--font-"],
|
|
300
|
+
entries: [{ name: "--font-size-7xl", value: "4.5rem" }]
|
|
301
|
+
});
|
|
302
|
+
return out;
|
|
303
|
+
}
|
|
304
|
+
};
|
|
305
|
+
|
|
221
306
|
// vite-plugin/files/dataPaths.ts
|
|
222
307
|
var import_fs = __toESM(require("fs"), 1);
|
|
223
308
|
var import_path = __toESM(require("path"), 1);
|
|
@@ -255,7 +340,9 @@ function readLiveTokensConfig() {
|
|
|
255
340
|
var TOKENS_CSS_MIGRATIONS = [
|
|
256
341
|
tokensCssMigration_2026_05_29_typographyScaleAdditions,
|
|
257
342
|
tokensCssMigration_2026_05_29_sectiondividerLegacyAxisCleanup,
|
|
258
|
-
tokensCssMigration_2026_06_03_transformScaleAdditions
|
|
343
|
+
tokensCssMigration_2026_06_03_transformScaleAdditions,
|
|
344
|
+
tokensCssMigration_2026_06_04_removeDeadSizeIconScale,
|
|
345
|
+
tokensCssMigration_2026_06_04_easingColorAndTypescaleAdditions
|
|
259
346
|
];
|
|
260
347
|
function runTokensCssMigrations(css) {
|
|
261
348
|
let out = css;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@motion-proto/live-tokens",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.32.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Design token editor with live CSS variable editing. Svelte 5 + Vite 8.",
|
|
6
6
|
"keywords": [
|
|
@@ -95,6 +95,7 @@
|
|
|
95
95
|
"deploy:local": "bash scripts/deploy-local.sh",
|
|
96
96
|
"check:no-style-imports": "node scripts/check-no-style-imports.mjs",
|
|
97
97
|
"check:slot-prose": "node scripts/check-slot-prose.mjs",
|
|
98
|
+
"check:overlay-portal": "node scripts/check-overlay-portal.mjs",
|
|
98
99
|
"check:editor-font-isolation": "node scripts/check-editor-font-isolation.mjs",
|
|
99
100
|
"check:component-defaults": "node scripts/sync-component-defaults.mjs --check",
|
|
100
101
|
"check:production-is-default": "node scripts/check-production-is-default.mjs",
|
|
@@ -104,7 +105,7 @@
|
|
|
104
105
|
"collapse:manifest": "node scripts/collapse-manifest-to-default.mjs",
|
|
105
106
|
"check:smoke-install": "bash scripts/smoke-install.sh",
|
|
106
107
|
"check:smoke-create": "bash scripts/smoke-create.sh",
|
|
107
|
-
"prepublishOnly": "npm run check:no-style-imports && npm run check:slot-prose && npm run check:editor-font-isolation && npm run check:component-defaults && npm run check:production-is-default && npm run check:docs-content && npm run build:lib && npm run check:smoke-install && npm run check:smoke-create"
|
|
108
|
+
"prepublishOnly": "npm run check:no-style-imports && npm run check:slot-prose && npm run check:overlay-portal && npm run check:editor-font-isolation && npm run check:component-defaults && npm run check:production-is-default && npm run check:docs-content && npm run build:lib && npm run check:smoke-install && npm run check:smoke-create"
|
|
108
109
|
},
|
|
109
110
|
"peerDependencies": {
|
|
110
111
|
"@sveltejs/vite-plugin-svelte": "^7.0",
|
|
@@ -16,7 +16,9 @@
|
|
|
16
16
|
|
|
17
17
|
export const allTokens: Token[] = Object.values(states).flat();
|
|
18
18
|
|
|
19
|
-
// Global
|
|
19
|
+
// Global zoom defaults. `none` = off; `scale(...)` = on. `--image-zoom-hover` scales the
|
|
20
|
+
// content within the masked frame (overflow scaling); `--image-grow-hover` scales the whole
|
|
21
|
+
// frame so it grows. At most one is ever `scale(...)`.
|
|
20
22
|
const ZOOM_ON = 'scale(var(--image-zoom-scale))';
|
|
21
23
|
export const intrinsics: IntrinsicSpec[] = [
|
|
22
24
|
{
|
|
@@ -26,6 +28,13 @@
|
|
|
26
28
|
values: ['none', ZOOM_ON],
|
|
27
29
|
default: { default: 'none' },
|
|
28
30
|
},
|
|
31
|
+
{
|
|
32
|
+
key: 'grow',
|
|
33
|
+
variants: ['default'],
|
|
34
|
+
variable: () => '--image-grow-hover',
|
|
35
|
+
values: ['none', ZOOM_ON],
|
|
36
|
+
default: { default: 'none' },
|
|
37
|
+
},
|
|
29
38
|
];
|
|
30
39
|
</script>
|
|
31
40
|
|
|
@@ -39,15 +48,22 @@
|
|
|
39
48
|
let aliases = $derived(
|
|
40
49
|
($editorState.components[component]?.aliases ?? {}) as Record<string, import('../core/store/editorTypes').CssVarRef>,
|
|
41
50
|
);
|
|
42
|
-
|
|
43
|
-
const ref = aliases[
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
51
|
+
function aliasValue(variable: string, fallback: string): string {
|
|
52
|
+
const ref = aliases[variable];
|
|
53
|
+
return ref?.kind === 'literal' ? ref.value : fallback;
|
|
54
|
+
}
|
|
55
|
+
let contentOn = $derived(aliasValue('--image-zoom-hover', intrinsics[0].default.default) === ZOOM_ON);
|
|
56
|
+
let frameOn = $derived(aliasValue('--image-grow-hover', intrinsics[1].default.default) === ZOOM_ON);
|
|
57
|
+
let useZoom = $derived(contentOn || frameOn);
|
|
58
|
+
// Overflow scaling = mask the zoom to the frame (the content path). Off = grow the frame.
|
|
59
|
+
let overflowScaling = $derived(!frameOn);
|
|
47
60
|
|
|
48
|
-
function
|
|
49
|
-
setComponentAlias(component, '--image-zoom-hover', { kind: 'literal', value:
|
|
61
|
+
function applyZoom(zoomOn: boolean, masked: boolean) {
|
|
62
|
+
setComponentAlias(component, '--image-zoom-hover', { kind: 'literal', value: zoomOn && masked ? ZOOM_ON : 'none' });
|
|
63
|
+
setComponentAlias(component, '--image-grow-hover', { kind: 'literal', value: zoomOn && !masked ? ZOOM_ON : 'none' });
|
|
50
64
|
}
|
|
65
|
+
const setUseZoom = (checked: boolean) => applyZoom(checked, overflowScaling);
|
|
66
|
+
const setOverflowScaling = (checked: boolean) => applyZoom(useZoom, checked);
|
|
51
67
|
</script>
|
|
52
68
|
|
|
53
69
|
<ComponentEditorBase {component} title="Image" description="Framed image with rounded corners, border, and shadow." tokens={allTokens}>
|
|
@@ -57,11 +73,17 @@
|
|
|
57
73
|
<input type="checkbox" checked={useZoom} onchange={(e) => setUseZoom(e.currentTarget.checked)} />
|
|
58
74
|
<span>Use zoom on hover</span>
|
|
59
75
|
</label>
|
|
76
|
+
<label class="zoom-enable" class:disabled={!useZoom}>
|
|
77
|
+
<input type="checkbox" checked={overflowScaling} disabled={!useZoom} onchange={(e) => setOverflowScaling(e.currentTarget.checked)} />
|
|
78
|
+
<span>Overflow scaling (mask zoom to frame)</span>
|
|
79
|
+
</label>
|
|
60
80
|
{/snippet}
|
|
61
|
-
<Image src={demoImageUrl} alt="Demo" variant="banner" zoom={useZoom ? undefined : false} />
|
|
81
|
+
<Image src={demoImageUrl} alt="Demo" variant="banner" zoom={useZoom ? undefined : false} {overflowScaling} />
|
|
62
82
|
<p class="zoom-help">
|
|
63
|
-
|
|
64
|
-
|
|
83
|
+
Use zoom on hover: every image scales on hover (a page can still force it per image with the
|
|
84
|
+
<code>zoom</code> prop). Overflow scaling on (default): the content zooms inside the fixed frame,
|
|
85
|
+
masked by overflow. Off: the whole framed image grows past its box. Override per image with
|
|
86
|
+
<code>overflowScaling</code>.
|
|
65
87
|
</p>
|
|
66
88
|
</VariantGroup>
|
|
67
89
|
</ComponentEditorBase>
|
|
@@ -75,6 +97,10 @@
|
|
|
75
97
|
color: var(--ui-text-secondary);
|
|
76
98
|
cursor: pointer;
|
|
77
99
|
}
|
|
100
|
+
.zoom-enable.disabled {
|
|
101
|
+
opacity: var(--ui-opacity-disabled);
|
|
102
|
+
cursor: not-allowed;
|
|
103
|
+
}
|
|
78
104
|
.zoom-help {
|
|
79
105
|
margin: var(--ui-space-8) 0 0;
|
|
80
106
|
font-size: var(--ui-font-size-sm);
|
|
@@ -33,18 +33,34 @@
|
|
|
33
33
|
import ImageLightbox from '../../system/components/ImageLightbox.svelte';
|
|
34
34
|
import VariantGroup from './scaffolding/VariantGroup.svelte';
|
|
35
35
|
import ComponentEditorBase from './scaffolding/ComponentEditorBase.svelte';
|
|
36
|
-
import
|
|
36
|
+
import offeringUrl from '../../system/assets/offering.webp';
|
|
37
|
+
import newspaperUrl from '../../system/assets/newspaper.webp';
|
|
38
|
+
|
|
39
|
+
const demoImages = [
|
|
40
|
+
// Offering carries explicit dimensions (the no-reflow path); Newspaper omits
|
|
41
|
+
// them to exercise self-measure from the loaded image.
|
|
42
|
+
{ src: offeringUrl, alt: 'Offering', width: 1455, height: 970 },
|
|
43
|
+
{ src: newspaperUrl, alt: 'Newspaper' },
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
let multiple = $state(true);
|
|
37
47
|
</script>
|
|
38
48
|
|
|
39
49
|
<ComponentEditorBase
|
|
40
50
|
{component}
|
|
41
51
|
title="Image Lightbox"
|
|
42
|
-
description="Click an inline image to expand it into a centered modal with a backdrop. Extended mode adds zoom controls and drag panning."
|
|
52
|
+
description="Click an inline image to expand it into a centered modal with a backdrop. Pass multiple images for a gallery (chevrons + counter). Extended mode adds zoom controls and drag panning."
|
|
43
53
|
tokens={allTokens}
|
|
44
54
|
>
|
|
45
55
|
<VariantGroup name="imagelightbox" title="Image Lightbox" {states} {component}>
|
|
56
|
+
{#snippet stateActions()}
|
|
57
|
+
<label class="preview-toggle">
|
|
58
|
+
<input type="checkbox" checked={multiple} onchange={(e) => (multiple = e.currentTarget.checked)} />
|
|
59
|
+
<span>Multiple images</span>
|
|
60
|
+
</label>
|
|
61
|
+
{/snippet}
|
|
46
62
|
<div class="preview-frame">
|
|
47
|
-
<ImageLightbox
|
|
63
|
+
<ImageLightbox images={multiple ? demoImages : [demoImages[0]]} extended />
|
|
48
64
|
</div>
|
|
49
65
|
</VariantGroup>
|
|
50
66
|
</ComponentEditorBase>
|
|
@@ -55,4 +71,12 @@
|
|
|
55
71
|
max-width: 28rem;
|
|
56
72
|
margin: 0 auto;
|
|
57
73
|
}
|
|
74
|
+
.preview-toggle {
|
|
75
|
+
display: inline-flex;
|
|
76
|
+
align-items: center;
|
|
77
|
+
gap: var(--ui-space-4);
|
|
78
|
+
font-size: var(--ui-font-size-sm);
|
|
79
|
+
color: var(--ui-text-secondary);
|
|
80
|
+
cursor: pointer;
|
|
81
|
+
}
|
|
58
82
|
</style>
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
import {
|
|
12
12
|
SPACING_VARS, BORDER_WIDTH_VARS, RADIUS_VARS, FONT_SIZE_VARS,
|
|
13
13
|
ICON_SIZE_VARS, FONT_WEIGHT_VARS, LINE_HEIGHT_VARS, LETTER_SPACING_VARS,
|
|
14
|
-
DURATION_TOKENS, Z_INDEX_TOKENS, OPACITY_TOKENS,
|
|
14
|
+
SCALE_VARS, DURATION_TOKENS, Z_INDEX_TOKENS, OPACITY_TOKENS,
|
|
15
15
|
} from './sections/tokenScales';
|
|
16
16
|
|
|
17
17
|
/** Visual flash for the copy-to-clipboard chip, kept short enough to
|
|
@@ -154,6 +154,11 @@
|
|
|
154
154
|
<h3 class="group-title">Opacity</h3>
|
|
155
155
|
<TokenScaleTable kind="line-height" tokens={OPACITY_TOKENS} {copiedVar} oncopy={copyVariable} />
|
|
156
156
|
</div>
|
|
157
|
+
|
|
158
|
+
<div class="utility-group">
|
|
159
|
+
<h3 class="group-title">Scale</h3>
|
|
160
|
+
<TokenScaleTable kind="line-height" vars={SCALE_VARS} {liveVersion} {copiedVar} oncopy={copyVariable} />
|
|
161
|
+
</div>
|
|
157
162
|
</div>
|
|
158
163
|
</section>
|
|
159
164
|
</div>
|
|
@@ -51,6 +51,10 @@ export const LETTER_SPACING_VARS = [
|
|
|
51
51
|
'--letter-spacing-wide', '--letter-spacing-wider',
|
|
52
52
|
] as const;
|
|
53
53
|
|
|
54
|
+
export const SCALE_VARS = [
|
|
55
|
+
'--scale-sm', '--scale-md', '--scale-lg', '--scale-xl', '--scale-2xl',
|
|
56
|
+
] as const;
|
|
57
|
+
|
|
54
58
|
export interface TokenItem {
|
|
55
59
|
variable: string;
|
|
56
60
|
value: string;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { createEventDispatcher, tick } from 'svelte';
|
|
3
3
|
import type { Snippet } from 'svelte';
|
|
4
|
+
import { portal } from '../internal/portal';
|
|
4
5
|
import Button from './Button.svelte';
|
|
5
6
|
import type { ButtonVariant, DialogButtonSpec } from './types';
|
|
6
7
|
|
|
@@ -105,7 +106,9 @@
|
|
|
105
106
|
</script>
|
|
106
107
|
|
|
107
108
|
{#if show}
|
|
108
|
-
|
|
109
|
+
<!-- The fixed backdrop portals to <body> to escape transformed/isolated
|
|
110
|
+
ancestors; the inline preview variant stays in flow. -->
|
|
111
|
+
<div class="dialog-backdrop" class:inline use:portal={!inline}>
|
|
109
112
|
<div class="dialog" style="width: {width}; max-width: {width};">
|
|
110
113
|
<div class="dialog-content">
|
|
111
114
|
{#if title}
|
|
@@ -7,6 +7,11 @@
|
|
|
7
7
|
/** Zoom the contents on hover (frame stays fixed). `undefined` inherits the editor's
|
|
8
8
|
global "Use zoom" default; `true`/`false` force this instance on/off. */
|
|
9
9
|
zoom?: boolean | undefined;
|
|
10
|
+
/** When zoom is active, decide what the hover scale grows. `true` (default) scales the
|
|
11
|
+
content inside the fixed frame, masked by overflow. `false` scales the whole framed
|
|
12
|
+
image so it grows past its layout box. `undefined` inherits the global default.
|
|
13
|
+
Set on its own (without `zoom`) it forces zoom on in the chosen mode. */
|
|
14
|
+
overflowScaling?: boolean | undefined;
|
|
10
15
|
srcset?: string | undefined;
|
|
11
16
|
sizes?: string | undefined;
|
|
12
17
|
/** Content images default to lazy; pass `'eager'` for above-the-fold heroes. */
|
|
@@ -20,6 +25,7 @@
|
|
|
20
25
|
variant = 'default',
|
|
21
26
|
height = undefined,
|
|
22
27
|
zoom = undefined,
|
|
28
|
+
overflowScaling = undefined,
|
|
23
29
|
srcset = undefined,
|
|
24
30
|
sizes = undefined,
|
|
25
31
|
loading = 'lazy',
|
|
@@ -35,13 +41,29 @@
|
|
|
35
41
|
|
|
36
42
|
let resolvedHeight = $derived(height ?? variantHeights[variant]);
|
|
37
43
|
|
|
38
|
-
// Per-instance override of the global zoom
|
|
39
|
-
|
|
40
|
-
|
|
44
|
+
// Per-instance override of the global zoom intrinsics. `undefined` for a variable leaves
|
|
45
|
+
// :root in charge. Exactly one of the two transforms is ever the scale (the other `none`),
|
|
46
|
+
// so contained and grow can't stack into a double zoom.
|
|
47
|
+
const ZOOM = 'scale(var(--image-zoom-scale))';
|
|
48
|
+
let zoomOff = $derived(zoom === false);
|
|
49
|
+
// Setting either prop forces zoom on; otherwise both inherit the global default.
|
|
50
|
+
let zoomForced = $derived(zoom === true || overflowScaling !== undefined);
|
|
51
|
+
let contained = $derived(overflowScaling !== false);
|
|
52
|
+
|
|
53
|
+
let contentHover = $derived(
|
|
54
|
+
zoomOff ? 'none' : zoomForced ? (contained ? ZOOM : 'none') : undefined,
|
|
55
|
+
);
|
|
56
|
+
let frameHover = $derived(
|
|
57
|
+
zoomOff ? 'none' : zoomForced ? (contained ? 'none' : ZOOM) : undefined,
|
|
41
58
|
);
|
|
42
59
|
</script>
|
|
43
60
|
|
|
44
|
-
<div
|
|
61
|
+
<div
|
|
62
|
+
class="image"
|
|
63
|
+
style:height={resolvedHeight}
|
|
64
|
+
style:--image-zoom-hover={contentHover}
|
|
65
|
+
style:--image-grow-hover={frameHover}
|
|
66
|
+
>
|
|
45
67
|
<img {src} {alt} {srcset} {sizes} {loading} {decoding} />
|
|
46
68
|
</div>
|
|
47
69
|
|
|
@@ -52,8 +74,11 @@
|
|
|
52
74
|
--image-default-border-width: var(--border-width-1);
|
|
53
75
|
--image-default-shadow: var(--shadow-md);
|
|
54
76
|
--image-zoom-scale: var(--scale-sm);
|
|
55
|
-
/*
|
|
77
|
+
/* Hover-scale targets. Contained mode (`overflowScaling`) scales the content within the
|
|
78
|
+
masked frame; grow mode scales the whole frame so it grows past its box. Each is `none`
|
|
79
|
+
(off) or `scale(var(--image-zoom-scale))` (on); only one is ever on at a time. */
|
|
56
80
|
--image-zoom-hover: none;
|
|
81
|
+
--image-grow-hover: none;
|
|
57
82
|
}
|
|
58
83
|
|
|
59
84
|
.image {
|
|
@@ -61,6 +86,8 @@
|
|
|
61
86
|
overflow: hidden;
|
|
62
87
|
border: var(--image-default-border-width) solid var(--image-default-border);
|
|
63
88
|
box-shadow: var(--image-default-shadow);
|
|
89
|
+
transform-origin: center;
|
|
90
|
+
transition: transform var(--duration-300) var(--ease-out-cubic);
|
|
64
91
|
}
|
|
65
92
|
|
|
66
93
|
img {
|
|
@@ -73,6 +100,10 @@
|
|
|
73
100
|
transition: transform var(--duration-300) var(--ease-out-cubic);
|
|
74
101
|
}
|
|
75
102
|
|
|
103
|
+
.image:hover {
|
|
104
|
+
transform: var(--image-grow-hover);
|
|
105
|
+
}
|
|
106
|
+
|
|
76
107
|
.image:hover img {
|
|
77
108
|
transform: var(--image-zoom-hover);
|
|
78
109
|
}
|