@urbicon-ui/blocks 6.33.0 → 6.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -1
- package/dist/components/Calendar/CalendarHeader.svelte +32 -26
- package/dist/components/Calendar/CalendarMiniMonth.svelte +10 -10
- package/dist/components/Calendar/calendar.variants.d.ts +63 -63
- package/dist/components/Calendar/calendar.variants.js +19 -5
- package/dist/components/FileUpload/FileUpload.svelte +17 -2
- package/dist/components/Planner/PlannerHeader.svelte +16 -13
- package/dist/components/Planner/planner.variants.js +14 -3
- package/dist/i18n/index.d.ts +467 -205
- package/dist/i18n/index.js +83 -9
- package/dist/internal/core/CoreIconButton.svelte +66 -0
- package/dist/internal/core/CoreIconButton.svelte.d.ts +13 -0
- package/dist/internal/core/CoreSpinner.svelte +49 -0
- package/dist/internal/core/CoreSpinner.svelte.d.ts +8 -0
- package/dist/internal/core/spinner-geometry.d.ts +6 -0
- package/dist/internal/core/spinner-geometry.js +6 -0
- package/dist/mint/README.md +33 -0
- package/dist/mint/compose.d.ts +7 -1
- package/dist/mint/compose.js +35 -8
- package/dist/mint/engine.d.ts +34 -0
- package/dist/mint/engine.js +106 -0
- package/dist/mint/index.d.ts +2 -2
- package/dist/mint/index.js +1 -1
- package/dist/mint/micro-interactions.d.ts +9 -3
- package/dist/mint/micro-interactions.js +18 -87
- package/dist/mint/presets.d.ts +7 -1
- package/dist/mint/presets.js +9 -3
- package/dist/mint/registry.d.ts +61 -4
- package/dist/mint/registry.js +99 -28
- package/dist/mint/ripple.js +1 -1
- package/dist/primitives/Alert/alert.variants.d.ts +8 -8
- package/dist/primitives/Badge/Badge.svelte +5 -5
- package/dist/primitives/Badge/badge.variants.js +17 -1
- package/dist/primitives/Button/Button.svelte +9 -3
- package/dist/primitives/Dialog/Dialog.svelte +7 -5
- package/dist/primitives/Dialog/dialog.variants.d.ts +7 -0
- package/dist/primitives/Dialog/dialog.variants.js +17 -0
- package/dist/primitives/Drawer/Drawer.svelte +7 -5
- package/dist/primitives/Drawer/drawer.variants.d.ts +8 -0
- package/dist/primitives/Drawer/drawer.variants.js +17 -0
- package/dist/primitives/JourneyTimeline/journey-timeline.variants.d.ts +22 -22
- package/dist/primitives/Spinner/Spinner.svelte +3 -1
- package/dist/primitives/Spinner/spinner.variants.d.ts +16 -16
- package/dist/primitives/Stepper/stepper.variants.d.ts +11 -11
- package/dist/primitives/Toast/Toaster.svelte +17 -2
- package/dist/primitives/Toast/toast.variants.d.ts +12 -12
- package/dist/primitives/Tooltip/tooltip.variants.d.ts +3 -3
- package/dist/utils/variants.js +44 -10
- package/package.json +4 -6
|
@@ -1,111 +1,42 @@
|
|
|
1
|
+
import { createMicroInteraction, prefersReducedMotion, scaleMint } from './engine.js';
|
|
1
2
|
/**
|
|
2
|
-
*
|
|
3
|
+
* Built-in micro-interaction registrations.
|
|
4
|
+
*
|
|
5
|
+
* The generic engine (`createMicroInteraction`) and the statically-shipped
|
|
6
|
+
* default (`scaleMint`) live in `./engine.ts` — this module must contain ONLY
|
|
7
|
+
* registration code, because it is reachable exclusively through the
|
|
8
|
+
* demand-loaded `./presets.ts` chunk. Anything defined here would otherwise
|
|
9
|
+
* be dragged back into every component's initial bundle once a statically
|
|
10
|
+
* imported module shared it (Rollup assigns a shared module's whole
|
|
11
|
+
* used-export-set to the chunk that statically owns it).
|
|
3
12
|
*/
|
|
4
|
-
function prefersReducedMotion() {
|
|
5
|
-
return window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
6
|
-
}
|
|
7
|
-
/**
|
|
8
|
-
* Generic micro-interaction factory
|
|
9
|
-
*/
|
|
10
|
-
export function createMicroInteraction(className, defaultConfig = {}) {
|
|
11
|
-
return {
|
|
12
|
-
init(el, config = {}) {
|
|
13
|
-
// Merge default config with provided config
|
|
14
|
-
const finalConfig = { ...defaultConfig, ...config };
|
|
15
|
-
// Skip if disabled or prefers reduced motion
|
|
16
|
-
if (finalConfig.disabled || prefersReducedMotion())
|
|
17
|
-
return;
|
|
18
|
-
const trigger = finalConfig.trigger || 'hover';
|
|
19
|
-
const duration = finalConfig.duration || 200;
|
|
20
|
-
const delay = finalConfig.delay || 0;
|
|
21
|
-
// Determine event based on trigger
|
|
22
|
-
const eventMap = {
|
|
23
|
-
hover: 'mouseenter',
|
|
24
|
-
click: 'click',
|
|
25
|
-
focus: 'focus',
|
|
26
|
-
load: 'load'
|
|
27
|
-
};
|
|
28
|
-
const event = eventMap[trigger] || 'mouseenter';
|
|
29
|
-
const handler = () => {
|
|
30
|
-
// Skip if this specific animation is already running
|
|
31
|
-
const animatingAttr = `data-animating-${className}`;
|
|
32
|
-
if (el.getAttribute(animatingAttr) === 'true')
|
|
33
|
-
return;
|
|
34
|
-
// Apply delay if specified
|
|
35
|
-
const applyAnimation = () => {
|
|
36
|
-
el.setAttribute(animatingAttr, 'true');
|
|
37
|
-
// Add dynamic styles if intensity is specified
|
|
38
|
-
if (finalConfig.intensity && className.includes('scale')) {
|
|
39
|
-
el.style.setProperty('--scale-intensity', finalConfig.intensity.toString());
|
|
40
|
-
}
|
|
41
|
-
el.classList.add(className);
|
|
42
|
-
const cleanup = () => {
|
|
43
|
-
el.classList.remove(className);
|
|
44
|
-
el.removeAttribute(animatingAttr);
|
|
45
|
-
el.style.removeProperty('--scale-intensity');
|
|
46
|
-
el.removeEventListener('animationend', cleanup);
|
|
47
|
-
el.removeEventListener('transitionend', cleanup);
|
|
48
|
-
};
|
|
49
|
-
el.addEventListener('animationend', cleanup, { once: true });
|
|
50
|
-
el.addEventListener('transitionend', cleanup, { once: true });
|
|
51
|
-
// Fallback timeout
|
|
52
|
-
setTimeout(cleanup, duration + 50);
|
|
53
|
-
};
|
|
54
|
-
if (delay > 0) {
|
|
55
|
-
setTimeout(applyAnimation, delay);
|
|
56
|
-
}
|
|
57
|
-
else {
|
|
58
|
-
applyAnimation();
|
|
59
|
-
}
|
|
60
|
-
};
|
|
61
|
-
// Special handling for load trigger
|
|
62
|
-
if (trigger === 'load') {
|
|
63
|
-
// Execute immediately if element is already loaded
|
|
64
|
-
requestAnimationFrame(() => handler());
|
|
65
|
-
}
|
|
66
|
-
else {
|
|
67
|
-
el.addEventListener(event, handler, { passive: true });
|
|
68
|
-
}
|
|
69
|
-
// Store cleanup function
|
|
70
|
-
this.destroy = () => {
|
|
71
|
-
if (event !== 'load') {
|
|
72
|
-
el.removeEventListener(event, handler);
|
|
73
|
-
}
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
13
|
/**
|
|
79
14
|
* Register all default micro-interaction mints.
|
|
80
15
|
* Called by registerDefaultMints() - not at module level.
|
|
81
16
|
*/
|
|
82
17
|
export function registerMicroInteractions(registry) {
|
|
83
|
-
registry.
|
|
84
|
-
|
|
85
|
-
duration: 200,
|
|
86
|
-
...config
|
|
87
|
-
}));
|
|
88
|
-
registry.register('translate', (config) => createMicroInteraction('blocks-mint-translate', {
|
|
18
|
+
registry.registerBuiltin('scale', scaleMint);
|
|
19
|
+
registry.registerBuiltin('translate', (config) => createMicroInteraction('blocks-mint-translate', {
|
|
89
20
|
trigger: 'hover',
|
|
90
21
|
duration: 200,
|
|
91
22
|
...config
|
|
92
23
|
}));
|
|
93
|
-
registry.
|
|
24
|
+
registry.registerBuiltin('rotate', (config) => createMicroInteraction('blocks-mint-rotate', {
|
|
94
25
|
trigger: 'hover',
|
|
95
26
|
duration: 200,
|
|
96
27
|
...config
|
|
97
28
|
}));
|
|
98
|
-
registry.
|
|
29
|
+
registry.registerBuiltin('glow', (config) => createMicroInteraction('blocks-mint-glow', {
|
|
99
30
|
trigger: 'hover',
|
|
100
31
|
duration: 300,
|
|
101
32
|
...config
|
|
102
33
|
}));
|
|
103
|
-
registry.
|
|
34
|
+
registry.registerBuiltin('bounce', (config) => createMicroInteraction('blocks-mint-bounce', {
|
|
104
35
|
trigger: 'click',
|
|
105
36
|
duration: 600,
|
|
106
37
|
...config
|
|
107
38
|
}));
|
|
108
|
-
registry.
|
|
39
|
+
registry.registerBuiltin('pulse', (config) => ({
|
|
109
40
|
init(el, inputConfig = {}) {
|
|
110
41
|
const finalConfig = { trigger: 'hover', ...config, ...inputConfig };
|
|
111
42
|
if (finalConfig.disabled || prefersReducedMotion())
|
|
@@ -143,12 +74,12 @@ export function registerMicroInteractions(registry) {
|
|
|
143
74
|
}
|
|
144
75
|
}
|
|
145
76
|
}));
|
|
146
|
-
registry.
|
|
77
|
+
registry.registerBuiltin('shake', (config) => createMicroInteraction('blocks-mint-shake', {
|
|
147
78
|
trigger: 'click',
|
|
148
79
|
duration: 500,
|
|
149
80
|
...config
|
|
150
81
|
}));
|
|
151
|
-
registry.
|
|
82
|
+
registry.registerBuiltin('wiggle', (config) => createMicroInteraction('blocks-mint-wiggle', {
|
|
152
83
|
trigger: 'hover',
|
|
153
84
|
duration: 500,
|
|
154
85
|
...config
|
package/dist/mint/presets.d.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Register all default mints (scale, translate, rotate, glow, bounce, pulse, shake, ripple, composite).
|
|
3
3
|
* Safe to call multiple times – subsequent calls are no-ops.
|
|
4
|
+
*
|
|
5
|
+
* All registrations go through `registerBuiltin` (register-if-absent), so a
|
|
6
|
+
* consumer `register()` override for a built-in name ALWAYS survives — no
|
|
7
|
+
* matter whether the override ran before this call or while the demand-load
|
|
8
|
+
* that triggers it was still in flight.
|
|
4
9
|
*/
|
|
5
10
|
export declare function registerDefaultMints(): void;
|
|
6
11
|
/**
|
|
@@ -12,7 +17,8 @@ export declare function registerDefaultMints(): void;
|
|
|
12
17
|
*/
|
|
13
18
|
export declare function registerPlayfulMints(): void;
|
|
14
19
|
/**
|
|
15
|
-
* Register business mints bundle
|
|
20
|
+
* Register business mints bundle.
|
|
21
|
+
* Registered via `registerBuiltin`: a consumer override for these names wins.
|
|
16
22
|
*/
|
|
17
23
|
export declare function registerBusinessMints(): void;
|
|
18
24
|
export declare const mintPresets: {
|
package/dist/mint/presets.js
CHANGED
|
@@ -6,6 +6,11 @@ let defaultMintsRegistered = false;
|
|
|
6
6
|
/**
|
|
7
7
|
* Register all default mints (scale, translate, rotate, glow, bounce, pulse, shake, ripple, composite).
|
|
8
8
|
* Safe to call multiple times – subsequent calls are no-ops.
|
|
9
|
+
*
|
|
10
|
+
* All registrations go through `registerBuiltin` (register-if-absent), so a
|
|
11
|
+
* consumer `register()` override for a built-in name ALWAYS survives — no
|
|
12
|
+
* matter whether the override ran before this call or while the demand-load
|
|
13
|
+
* that triggers it was still in flight.
|
|
9
14
|
*/
|
|
10
15
|
export function registerDefaultMints() {
|
|
11
16
|
if (defaultMintsRegistered)
|
|
@@ -26,16 +31,17 @@ export function registerPlayfulMints() {
|
|
|
26
31
|
// Reserved for future playful-only mints.
|
|
27
32
|
}
|
|
28
33
|
/**
|
|
29
|
-
* Register business mints bundle
|
|
34
|
+
* Register business mints bundle.
|
|
35
|
+
* Registered via `registerBuiltin`: a consumer override for these names wins.
|
|
30
36
|
*/
|
|
31
37
|
export function registerBusinessMints() {
|
|
32
38
|
// Subtle mints for professional UIs
|
|
33
|
-
mintRegistry.
|
|
39
|
+
mintRegistry.registerBuiltin('fade', () => ({
|
|
34
40
|
init(el) {
|
|
35
41
|
el.classList.add('blocks-mint-fade');
|
|
36
42
|
}
|
|
37
43
|
}));
|
|
38
|
-
mintRegistry.
|
|
44
|
+
mintRegistry.registerBuiltin('slide', () => ({
|
|
39
45
|
init(el) {
|
|
40
46
|
el.classList.add('blocks-mint-slide');
|
|
41
47
|
}
|
package/dist/mint/registry.d.ts
CHANGED
|
@@ -1,22 +1,79 @@
|
|
|
1
1
|
import type { MintConfig, MintFactory, MintProp } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Statically-imported fallback factories, keyed by mint name.
|
|
4
|
+
*
|
|
5
|
+
* Components pass their *default* mint's factory here — Button imports
|
|
6
|
+
* `scaleMint` directly and calls `mintRegistry.apply(el, mint, { scale:
|
|
7
|
+
* scaleMint })` — so the default effect ships tree-shaken with the component
|
|
8
|
+
* instead of dragging the whole built-in set (micro-interactions, the ripple
|
|
9
|
+
* engine, compose, presets — ~3.9 KB min) into every consumer bundle. Same
|
|
10
|
+
* precedence as `resolveIcon(name, fallback)`: a registry entry (consumer
|
|
11
|
+
* override / loaded built-in) wins, the direct import is only the fallback.
|
|
12
|
+
* See docs/ICON-DESIGN.md → "Icon resolution & tree-shaking".
|
|
13
|
+
*/
|
|
14
|
+
export type MintFallbacks = Readonly<Partial<Record<string, MintFactory>>>;
|
|
15
|
+
/**
|
|
16
|
+
* @internal Shared with ./compose.ts so composite string members resolve
|
|
17
|
+
* through the same demand-load; not part of the public API.
|
|
18
|
+
*/
|
|
19
|
+
export declare function loadBuiltinMints(): Promise<void>;
|
|
2
20
|
declare class MintRegistry {
|
|
3
21
|
private mints;
|
|
4
22
|
private instances;
|
|
5
23
|
/** Register a mint globally */
|
|
6
24
|
register<TConfig extends MintConfig = MintConfig>(name: string, factory: MintFactory<TConfig>): void;
|
|
25
|
+
/**
|
|
26
|
+
* Register a built-in mint — only if the name is still free. Used by the
|
|
27
|
+
* built-in set (`registerDefaultMints()` and the opt-in bundles) so the
|
|
28
|
+
* demand-load NEVER clobbers a consumer override: a `register()` entry
|
|
29
|
+
* survives regardless of whether it ran before or during the load. A later
|
|
30
|
+
* explicit `register()` call still overrides as before.
|
|
31
|
+
*/
|
|
32
|
+
registerBuiltin<TConfig extends MintConfig = MintConfig>(name: string, factory: MintFactory<TConfig>): void;
|
|
7
33
|
/** Get a mint factory by name */
|
|
8
34
|
get(name: string): MintFactory | undefined;
|
|
9
35
|
/** Check if a mint is registered */
|
|
10
36
|
has(name: string): boolean;
|
|
11
|
-
/**
|
|
12
|
-
|
|
37
|
+
/**
|
|
38
|
+
* Apply mints to an element using polymorphic input.
|
|
39
|
+
*
|
|
40
|
+
* Resolution order per name: registry entry (consumer `register()` override
|
|
41
|
+
* or an already-loaded built-in) → `fallbacks` (statically imported by the
|
|
42
|
+
* caller) → lazy-loaded built-in set. Names that resolve synchronously are
|
|
43
|
+
* applied synchronously; unresolved names wait for the built-ins chunk
|
|
44
|
+
* (one-time microtask + fetch). Events firing inside that fetch window are
|
|
45
|
+
* NOT replayed — on a slow network, a click landing before a demand-loaded
|
|
46
|
+
* click-triggered mint (ripple, shake) finished loading is lost for that
|
|
47
|
+
* effect. Acceptable for decorative effects (documented contract, see
|
|
48
|
+
* mint/README.md); consumers who need first-interaction guarantees register
|
|
49
|
+
* the effect statically up front (`registerDefaultMints()`).
|
|
50
|
+
*
|
|
51
|
+
* One apply() per element: a second apply() on the same element replaces
|
|
52
|
+
* the instances map the first one registered, and the first cleanup then
|
|
53
|
+
* deletes it — `update()` for the second application would go dead. Every
|
|
54
|
+
* in-repo caller pairs exactly one apply() per element with its `$effect`
|
|
55
|
+
* teardown, which upholds this.
|
|
56
|
+
*/
|
|
57
|
+
apply(el: HTMLElement, mint: MintProp, fallbacks?: MintFallbacks): () => void;
|
|
13
58
|
/** Normalize polymorphic mint prop to consistent format */
|
|
14
59
|
private normalizeMintProp;
|
|
15
|
-
/**
|
|
60
|
+
/**
|
|
61
|
+
* Update mint config for an element.
|
|
62
|
+
*
|
|
63
|
+
* No-op for a name still inside the demand-load fetch window (it is not in
|
|
64
|
+
* the element's instances map yet) — same decorative-effect contract as the
|
|
65
|
+
* lost-first-interaction case documented on `apply()`.
|
|
66
|
+
*/
|
|
16
67
|
update(el: HTMLElement, name: string, config: MintConfig): void;
|
|
17
68
|
/** List all registered mint names */
|
|
18
69
|
list(): string[];
|
|
19
|
-
/**
|
|
70
|
+
/**
|
|
71
|
+
* Clear all mints. Test-only escape hatch: this does NOT reset the
|
|
72
|
+
* demand-load latch (`builtinsLoading` here, `defaultMintsRegistered` in
|
|
73
|
+
* ./presets.ts), so built-ins stay gone until a module reload — tests use
|
|
74
|
+
* `vi.resetModules()` for a fresh registry. Pre-existing behaviour from the
|
|
75
|
+
* eager-registration era, kept as-is.
|
|
76
|
+
*/
|
|
20
77
|
clear(): void;
|
|
21
78
|
}
|
|
22
79
|
export declare const mintRegistry: MintRegistry;
|
package/dist/mint/registry.js
CHANGED
|
@@ -1,4 +1,24 @@
|
|
|
1
|
-
|
|
1
|
+
// Lazily loads + registers the built-in mints (scale, glow, ripple, …) the
|
|
2
|
+
// first time a name resolves neither from the registry nor from the caller's
|
|
3
|
+
// fallbacks. The dynamic import() keeps the built-in set out of the static
|
|
4
|
+
// module graph of every mint-consuming component — an app that only ever uses
|
|
5
|
+
// component defaults never loads it at all; an app that passes a dynamic mint
|
|
6
|
+
// name (mint="ripple", presets, composite) fetches it once on first use.
|
|
7
|
+
//
|
|
8
|
+
// The registry ↔ presets import is cyclic but inert: presets dereferences the
|
|
9
|
+
// registry binding only at call time, and this side is a dynamic import, so
|
|
10
|
+
// module initialisation completes cleanly regardless of load order.
|
|
11
|
+
let builtinsLoading;
|
|
12
|
+
/**
|
|
13
|
+
* @internal Shared with ./compose.ts so composite string members resolve
|
|
14
|
+
* through the same demand-load; not part of the public API.
|
|
15
|
+
*/
|
|
16
|
+
export function loadBuiltinMints() {
|
|
17
|
+
builtinsLoading ??= import('./presets.js').then((presets) => {
|
|
18
|
+
presets.registerDefaultMints();
|
|
19
|
+
});
|
|
20
|
+
return builtinsLoading;
|
|
21
|
+
}
|
|
2
22
|
class MintRegistry {
|
|
3
23
|
mints = new Map();
|
|
4
24
|
instances = new WeakMap();
|
|
@@ -6,6 +26,18 @@ class MintRegistry {
|
|
|
6
26
|
register(name, factory) {
|
|
7
27
|
this.mints.set(name, factory);
|
|
8
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* Register a built-in mint — only if the name is still free. Used by the
|
|
31
|
+
* built-in set (`registerDefaultMints()` and the opt-in bundles) so the
|
|
32
|
+
* demand-load NEVER clobbers a consumer override: a `register()` entry
|
|
33
|
+
* survives regardless of whether it ran before or during the load. A later
|
|
34
|
+
* explicit `register()` call still overrides as before.
|
|
35
|
+
*/
|
|
36
|
+
registerBuiltin(name, factory) {
|
|
37
|
+
if (!this.mints.has(name)) {
|
|
38
|
+
this.mints.set(name, factory);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
9
41
|
/** Get a mint factory by name */
|
|
10
42
|
get(name) {
|
|
11
43
|
return this.mints.get(name);
|
|
@@ -14,43 +46,70 @@ class MintRegistry {
|
|
|
14
46
|
has(name) {
|
|
15
47
|
return this.mints.has(name);
|
|
16
48
|
}
|
|
17
|
-
/**
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
49
|
+
/**
|
|
50
|
+
* Apply mints to an element using polymorphic input.
|
|
51
|
+
*
|
|
52
|
+
* Resolution order per name: registry entry (consumer `register()` override
|
|
53
|
+
* or an already-loaded built-in) → `fallbacks` (statically imported by the
|
|
54
|
+
* caller) → lazy-loaded built-in set. Names that resolve synchronously are
|
|
55
|
+
* applied synchronously; unresolved names wait for the built-ins chunk
|
|
56
|
+
* (one-time microtask + fetch). Events firing inside that fetch window are
|
|
57
|
+
* NOT replayed — on a slow network, a click landing before a demand-loaded
|
|
58
|
+
* click-triggered mint (ripple, shake) finished loading is lost for that
|
|
59
|
+
* effect. Acceptable for decorative effects (documented contract, see
|
|
60
|
+
* mint/README.md); consumers who need first-interaction guarantees register
|
|
61
|
+
* the effect statically up front (`registerDefaultMints()`).
|
|
62
|
+
*
|
|
63
|
+
* One apply() per element: a second apply() on the same element replaces
|
|
64
|
+
* the instances map the first one registered, and the first cleanup then
|
|
65
|
+
* deletes it — `update()` for the second application would go dead. Every
|
|
66
|
+
* in-repo caller pairs exactly one apply() per element with its `$effect`
|
|
67
|
+
* teardown, which upholds this.
|
|
68
|
+
*/
|
|
69
|
+
apply(el, mint, fallbacks) {
|
|
30
70
|
const mintDefinitions = this.normalizeMintProp(mint);
|
|
31
71
|
const elementMints = new Map();
|
|
32
72
|
const cleanupFunctions = [];
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const config = typeof mintDef === 'object' ? mintDef.config : undefined;
|
|
36
|
-
const factory = this.get(name);
|
|
37
|
-
if (!factory) {
|
|
38
|
-
console.warn(`[MintRegistry] Unknown mint: ${name}`);
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
73
|
+
let disposed = false;
|
|
74
|
+
const applyOne = (name, config, factory) => {
|
|
41
75
|
const mintInstance = factory(config);
|
|
42
76
|
mintInstance.init(el, config);
|
|
43
77
|
elementMints.set(name, mintInstance);
|
|
44
|
-
|
|
45
|
-
const cleanup = () => {
|
|
78
|
+
cleanupFunctions.push(() => {
|
|
46
79
|
mintInstance.destroy?.(el);
|
|
47
80
|
elementMints.delete(name);
|
|
48
|
-
};
|
|
49
|
-
|
|
81
|
+
});
|
|
82
|
+
};
|
|
83
|
+
const unresolved = [];
|
|
84
|
+
mintDefinitions.forEach((mintDef) => {
|
|
85
|
+
const name = typeof mintDef === 'string' ? mintDef : mintDef.name;
|
|
86
|
+
const config = typeof mintDef === 'object' ? mintDef.config : undefined;
|
|
87
|
+
const factory = this.get(name) ?? fallbacks?.[name];
|
|
88
|
+
if (factory) {
|
|
89
|
+
applyOne(name, config, factory);
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
unresolved.push({ name, config });
|
|
93
|
+
}
|
|
50
94
|
});
|
|
95
|
+
if (unresolved.length > 0) {
|
|
96
|
+
void loadBuiltinMints().then(() => {
|
|
97
|
+
if (disposed)
|
|
98
|
+
return;
|
|
99
|
+
unresolved.forEach(({ name, config }) => {
|
|
100
|
+
const factory = this.get(name) ?? fallbacks?.[name];
|
|
101
|
+
if (!factory) {
|
|
102
|
+
console.warn(`[MintRegistry] Unknown mint: ${name}`);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
applyOne(name, config, factory);
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
}
|
|
51
109
|
this.instances.set(el, elementMints);
|
|
52
110
|
// Return combined cleanup function
|
|
53
111
|
return () => {
|
|
112
|
+
disposed = true;
|
|
54
113
|
cleanupFunctions.forEach((fn) => {
|
|
55
114
|
fn();
|
|
56
115
|
});
|
|
@@ -70,7 +129,13 @@ class MintRegistry {
|
|
|
70
129
|
}
|
|
71
130
|
return [];
|
|
72
131
|
}
|
|
73
|
-
/**
|
|
132
|
+
/**
|
|
133
|
+
* Update mint config for an element.
|
|
134
|
+
*
|
|
135
|
+
* No-op for a name still inside the demand-load fetch window (it is not in
|
|
136
|
+
* the element's instances map yet) — same decorative-effect contract as the
|
|
137
|
+
* lost-first-interaction case documented on `apply()`.
|
|
138
|
+
*/
|
|
74
139
|
update(el, name, config) {
|
|
75
140
|
const elementMints = this.instances.get(el);
|
|
76
141
|
const mint = elementMints?.get(name);
|
|
@@ -82,7 +147,13 @@ class MintRegistry {
|
|
|
82
147
|
list() {
|
|
83
148
|
return Array.from(this.mints.keys());
|
|
84
149
|
}
|
|
85
|
-
/**
|
|
150
|
+
/**
|
|
151
|
+
* Clear all mints. Test-only escape hatch: this does NOT reset the
|
|
152
|
+
* demand-load latch (`builtinsLoading` here, `defaultMintsRegistered` in
|
|
153
|
+
* ./presets.ts), so built-ins stay gone until a module reload — tests use
|
|
154
|
+
* `vi.resetModules()` for a fresh registry. Pre-existing behaviour from the
|
|
155
|
+
* eager-registration era, kept as-is.
|
|
156
|
+
*/
|
|
86
157
|
clear() {
|
|
87
158
|
this.mints.clear();
|
|
88
159
|
}
|
package/dist/mint/ripple.js
CHANGED
|
@@ -68,5 +68,5 @@ export function createRippleMint(defaultConfig = {}) {
|
|
|
68
68
|
* Called by registerDefaultMints() - not at module level.
|
|
69
69
|
*/
|
|
70
70
|
export function registerRipple(registry) {
|
|
71
|
-
registry.
|
|
71
|
+
registry.registerBuiltin('ripple', createRippleMint);
|
|
72
72
|
}
|
|
@@ -1,53 +1,53 @@
|
|
|
1
1
|
import { type SlotNames, type VariantProps } from '../../utils/variants.js';
|
|
2
2
|
export declare const alertVariants: ((props?: {
|
|
3
|
-
intent?: "
|
|
3
|
+
intent?: "info" | "primary" | "success" | "warning" | "danger" | "neutral" | undefined;
|
|
4
4
|
variant?: "inline" | "filled" | "soft" | undefined;
|
|
5
5
|
size?: "sm" | "md" | "lg" | undefined;
|
|
6
6
|
} | undefined) => {
|
|
7
7
|
base: (props?: ({
|
|
8
|
-
intent?: "
|
|
8
|
+
intent?: "info" | "primary" | "success" | "warning" | "danger" | "neutral" | undefined;
|
|
9
9
|
variant?: "inline" | "filled" | "soft" | undefined;
|
|
10
10
|
size?: "sm" | "md" | "lg" | undefined;
|
|
11
11
|
} & {
|
|
12
12
|
class?: string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | /*elided*/ any | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined;
|
|
13
13
|
}) | undefined) => string;
|
|
14
14
|
icon: (props?: ({
|
|
15
|
-
intent?: "
|
|
15
|
+
intent?: "info" | "primary" | "success" | "warning" | "danger" | "neutral" | undefined;
|
|
16
16
|
variant?: "inline" | "filled" | "soft" | undefined;
|
|
17
17
|
size?: "sm" | "md" | "lg" | undefined;
|
|
18
18
|
} & {
|
|
19
19
|
class?: string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | /*elided*/ any | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined;
|
|
20
20
|
}) | undefined) => string;
|
|
21
21
|
content: (props?: ({
|
|
22
|
-
intent?: "
|
|
22
|
+
intent?: "info" | "primary" | "success" | "warning" | "danger" | "neutral" | undefined;
|
|
23
23
|
variant?: "inline" | "filled" | "soft" | undefined;
|
|
24
24
|
size?: "sm" | "md" | "lg" | undefined;
|
|
25
25
|
} & {
|
|
26
26
|
class?: string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | /*elided*/ any | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined;
|
|
27
27
|
}) | undefined) => string;
|
|
28
28
|
title: (props?: ({
|
|
29
|
-
intent?: "
|
|
29
|
+
intent?: "info" | "primary" | "success" | "warning" | "danger" | "neutral" | undefined;
|
|
30
30
|
variant?: "inline" | "filled" | "soft" | undefined;
|
|
31
31
|
size?: "sm" | "md" | "lg" | undefined;
|
|
32
32
|
} & {
|
|
33
33
|
class?: string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | /*elided*/ any | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined;
|
|
34
34
|
}) | undefined) => string;
|
|
35
35
|
description: (props?: ({
|
|
36
|
-
intent?: "
|
|
36
|
+
intent?: "info" | "primary" | "success" | "warning" | "danger" | "neutral" | undefined;
|
|
37
37
|
variant?: "inline" | "filled" | "soft" | undefined;
|
|
38
38
|
size?: "sm" | "md" | "lg" | undefined;
|
|
39
39
|
} & {
|
|
40
40
|
class?: string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | /*elided*/ any | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined;
|
|
41
41
|
}) | undefined) => string;
|
|
42
42
|
actions: (props?: ({
|
|
43
|
-
intent?: "
|
|
43
|
+
intent?: "info" | "primary" | "success" | "warning" | "danger" | "neutral" | undefined;
|
|
44
44
|
variant?: "inline" | "filled" | "soft" | undefined;
|
|
45
45
|
size?: "sm" | "md" | "lg" | undefined;
|
|
46
46
|
} & {
|
|
47
47
|
class?: string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | (string | number | false | /*elided*/ any | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined)[] | Record<string, boolean | null | undefined> | null | undefined;
|
|
48
48
|
}) | undefined) => string;
|
|
49
49
|
dismissButton: (props?: ({
|
|
50
|
-
intent?: "
|
|
50
|
+
intent?: "info" | "primary" | "success" | "warning" | "danger" | "neutral" | undefined;
|
|
51
51
|
variant?: "inline" | "filled" | "soft" | undefined;
|
|
52
52
|
size?: "sm" | "md" | "lg" | undefined;
|
|
53
53
|
} & {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import {
|
|
2
|
+
import { mintRegistry } from '../..';
|
|
3
|
+
// internal core, not the public component — keeps the public-to-public import graph clean (see internal/core/)
|
|
4
|
+
import CoreIconButton from '../../internal/core/CoreIconButton.svelte';
|
|
3
5
|
import { getBlocksConfig, resolveSlotClasses } from '../../provider';
|
|
4
6
|
import { resolveIcon } from '../../icons';
|
|
5
7
|
import CloseIconDefault from '../../icons/CloseIcon.svelte';
|
|
@@ -152,9 +154,7 @@
|
|
|
152
154
|
{/if}
|
|
153
155
|
|
|
154
156
|
{#if isRemovable}
|
|
155
|
-
<
|
|
156
|
-
variant="ghost"
|
|
157
|
-
size="xs"
|
|
157
|
+
<CoreIconButton
|
|
158
158
|
{disabled}
|
|
159
159
|
class={unstyled
|
|
160
160
|
? (slotClasses?.removeButton ?? '')
|
|
@@ -167,7 +167,7 @@
|
|
|
167
167
|
? (slotClasses?.removeIcon ?? '')
|
|
168
168
|
: styles.removeIcon({ class: slotClasses?.removeIcon })}
|
|
169
169
|
/>
|
|
170
|
-
</
|
|
170
|
+
</CoreIconButton>
|
|
171
171
|
{/if}
|
|
172
172
|
</span>
|
|
173
173
|
|
|
@@ -23,9 +23,25 @@ export const badgeVariants = tv({
|
|
|
23
23
|
// arbitrary property inherits `base`'s per-size gap. (Codeberg #21)
|
|
24
24
|
content: ['flex items-center [gap:inherit]'],
|
|
25
25
|
// tier: modify — small remove-control on a commit-tier badge.
|
|
26
|
+
//
|
|
27
|
+
// Rendered on the internal CoreIconButton (behaviour-only base: inline-flex
|
|
28
|
+
// centring, cursor/select, focus-visible reset, disabled inertness), so this
|
|
29
|
+
// slot carries the FULL visual identity. The class set below is the exact
|
|
30
|
+
// fold of the `<Button variant="ghost" size="xs">` (intent neutral, tier
|
|
31
|
+
// commit) this control used to be — the ghost/xs Button base plus the
|
|
32
|
+
// remove-control overrides — MINUS the classes CoreIconButton already
|
|
33
|
+
// supplies. Effective render is byte-identical to the pre-extraction Badge,
|
|
34
|
+
// so the removable VR baseline stays green (see internal/core/).
|
|
26
35
|
removeButton: [
|
|
36
|
+
// ghost/xs neutral Button base (the part CoreIconButton does not supply)
|
|
37
|
+
'relative font-medium text-center whitespace-nowrap border overflow-hidden',
|
|
38
|
+
'duration-[var(--blocks-duration-fast)] ease-out',
|
|
39
|
+
'bg-transparent border-transparent shadow-none',
|
|
40
|
+
'hover:shadow-[var(--blocks-shadow-md)] active:scale-[0.98] active:shadow-[var(--blocks-shadow-sm)]',
|
|
41
|
+
'h-6 px-2 text-xs gap-1 focus-visible:ring-offset-2',
|
|
42
|
+
// remove-control overrides (won the fold over the ghost base)
|
|
27
43
|
'ml-1 shrink-0 rounded-modify transition-colors text-current',
|
|
28
|
-
'hover:bg-neutral-950/10 focus-visible:
|
|
44
|
+
'hover:bg-neutral-950/10 focus-visible:ring-1 focus-visible:ring-current'
|
|
29
45
|
],
|
|
30
46
|
removeIcon: ['w-3 h-3']
|
|
31
47
|
},
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { mintRegistry
|
|
2
|
+
import { mintRegistry } from '../..';
|
|
3
|
+
// internal core, not the public component — keeps the public-to-public import graph clean (see internal/core/)
|
|
4
|
+
import CoreSpinner from '../../internal/core/CoreSpinner.svelte';
|
|
5
|
+
// Direct import (not the barrel): the resolveIcon tree-shaking pattern.
|
|
6
|
+
// Button's mint default is 'scale', so the scale factory ships statically
|
|
7
|
+
// as the apply() fallback; every other mint name stays demand-loaded.
|
|
8
|
+
import { scaleMint } from '../../mint/engine';
|
|
3
9
|
import { getBlocksConfig, resolveSlotClasses } from '../../provider';
|
|
4
10
|
import { getButtonGroupContext } from '../ButtonGroup/buttonGroup.context';
|
|
5
11
|
import { buttonVariants, type ButtonVariants } from '..';
|
|
@@ -80,7 +86,7 @@
|
|
|
80
86
|
!effectiveDisabled &&
|
|
81
87
|
!loading
|
|
82
88
|
) {
|
|
83
|
-
return mintRegistry.apply(buttonElement, effectiveMint);
|
|
89
|
+
return mintRegistry.apply(buttonElement, effectiveMint, { scale: scaleMint });
|
|
84
90
|
}
|
|
85
91
|
});
|
|
86
92
|
|
|
@@ -150,7 +156,7 @@
|
|
|
150
156
|
: styles.spinner({ class: slotClasses?.spinner })}
|
|
151
157
|
aria-hidden="true"
|
|
152
158
|
>
|
|
153
|
-
<
|
|
159
|
+
<CoreSpinner size={spinnerSizeMap[effectiveSize]} />
|
|
154
160
|
</span>
|
|
155
161
|
|
|
156
162
|
<span
|