@urbicon-ui/blocks 6.34.0 → 6.36.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.js +19 -5
- package/dist/components/Chat/Chat/Chat.svelte +53 -0
- package/dist/components/Chat/Chat/Chat.svelte.d.ts +4 -0
- package/dist/components/Chat/Chat/chat.variants.d.ts +20 -0
- package/dist/components/Chat/Chat/chat.variants.js +15 -0
- package/dist/components/Chat/Chat/index.d.ts +47 -0
- package/dist/components/Chat/Chat/index.js +2 -0
- package/dist/components/Chat/ChatMessage/ChatMessage.svelte +342 -0
- package/dist/components/Chat/ChatMessage/ChatMessage.svelte.d.ts +4 -0
- package/dist/components/Chat/ChatMessage/chat-message.variants.d.ts +138 -0
- package/dist/components/Chat/ChatMessage/chat-message.variants.js +118 -0
- package/dist/components/Chat/ChatMessage/index.d.ts +102 -0
- package/dist/components/Chat/ChatMessage/index.js +2 -0
- package/dist/components/Chat/ChatMessageList/ChatMessageList.svelte +301 -0
- package/dist/components/Chat/ChatMessageList/ChatMessageList.svelte.d.ts +6 -0
- package/dist/components/Chat/ChatMessageList/chat-message-list.variants.d.ts +23 -0
- package/dist/components/Chat/ChatMessageList/chat-message-list.variants.js +32 -0
- package/dist/components/Chat/ChatMessageList/chat-scroll.d.ts +45 -0
- package/dist/components/Chat/ChatMessageList/chat-scroll.js +52 -0
- package/dist/components/Chat/ChatMessageList/index.d.ts +93 -0
- package/dist/components/Chat/ChatMessageList/index.js +3 -0
- package/dist/components/Chat/CitationChip/CitationChip.svelte +107 -0
- package/dist/components/Chat/CitationChip/CitationChip.svelte.d.ts +4 -0
- package/dist/components/Chat/CitationChip/citation-chip.variants.d.ts +40 -0
- package/dist/components/Chat/CitationChip/citation-chip.variants.js +42 -0
- package/dist/components/Chat/CitationChip/index.d.ts +69 -0
- package/dist/components/Chat/CitationChip/index.js +2 -0
- package/dist/components/Chat/CodeBlock/CodeBlock.svelte +120 -0
- package/dist/components/Chat/CodeBlock/CodeBlock.svelte.d.ts +4 -0
- package/dist/components/Chat/CodeBlock/code-block.variants.d.ts +40 -0
- package/dist/components/Chat/CodeBlock/code-block.variants.js +51 -0
- package/dist/components/Chat/CodeBlock/index.d.ts +55 -0
- package/dist/components/Chat/CodeBlock/index.js +2 -0
- package/dist/components/Chat/PromptInput/PromptInput.svelte +432 -0
- package/dist/components/Chat/PromptInput/PromptInput.svelte.d.ts +4 -0
- package/dist/components/Chat/PromptInput/index.d.ts +165 -0
- package/dist/components/Chat/PromptInput/index.js +2 -0
- package/dist/components/Chat/PromptInput/prompt-input.variants.d.ts +90 -0
- package/dist/components/Chat/PromptInput/prompt-input.variants.js +102 -0
- package/dist/components/Chat/ReasoningDisclosure/ReasoningDisclosure.svelte +107 -0
- package/dist/components/Chat/ReasoningDisclosure/ReasoningDisclosure.svelte.d.ts +4 -0
- package/dist/components/Chat/ReasoningDisclosure/index.d.ts +85 -0
- package/dist/components/Chat/ReasoningDisclosure/index.js +2 -0
- package/dist/components/Chat/ReasoningDisclosure/reasoning-disclosure.variants.d.ts +20 -0
- package/dist/components/Chat/ReasoningDisclosure/reasoning-disclosure.variants.js +31 -0
- package/dist/components/Chat/StreamingMarkdown/MdBlock.svelte +99 -0
- package/dist/components/Chat/StreamingMarkdown/MdBlock.svelte.d.ts +9 -0
- package/dist/components/Chat/StreamingMarkdown/MdInline.svelte +82 -0
- package/dist/components/Chat/StreamingMarkdown/MdInline.svelte.d.ts +9 -0
- package/dist/components/Chat/StreamingMarkdown/StreamingMarkdown.svelte +118 -0
- package/dist/components/Chat/StreamingMarkdown/StreamingMarkdown.svelte.d.ts +4 -0
- package/dist/components/Chat/StreamingMarkdown/index.d.ts +86 -0
- package/dist/components/Chat/StreamingMarkdown/index.js +2 -0
- package/dist/components/Chat/StreamingMarkdown/md-context.d.ts +58 -0
- package/dist/components/Chat/StreamingMarkdown/md-context.js +1 -0
- package/dist/components/Chat/StreamingMarkdown/streaming-markdown.variants.d.ts +145 -0
- package/dist/components/Chat/StreamingMarkdown/streaming-markdown.variants.js +73 -0
- package/dist/components/Chat/ToolCallCard/ToolCallCard.svelte +174 -0
- package/dist/components/Chat/ToolCallCard/ToolCallCard.svelte.d.ts +4 -0
- package/dist/components/Chat/ToolCallCard/index.d.ts +84 -0
- package/dist/components/Chat/ToolCallCard/index.js +2 -0
- package/dist/components/Chat/ToolCallCard/tool-call-card.variants.d.ts +38 -0
- package/dist/components/Chat/ToolCallCard/tool-call-card.variants.js +38 -0
- package/dist/components/Chat/chat.types.d.ts +82 -0
- package/dist/components/Chat/chat.types.js +7 -0
- package/dist/components/Chat/index.d.ts +22 -0
- package/dist/components/Chat/index.js +14 -0
- package/dist/components/Chat/markdown/blocks.d.ts +54 -0
- package/dist/components/Chat/markdown/blocks.js +462 -0
- package/dist/components/Chat/markdown/inline.d.ts +31 -0
- package/dist/components/Chat/markdown/inline.js +446 -0
- package/dist/components/Chat/markdown/repair.d.ts +23 -0
- package/dist/components/Chat/markdown/repair.js +337 -0
- package/dist/components/Chat/markdown/streaming-harness.d.ts +23 -0
- package/dist/components/Chat/markdown/streaming-harness.js +62 -0
- package/dist/components/Chat/markdown/types.d.ts +139 -0
- package/dist/components/Chat/markdown/types.js +13 -0
- package/dist/components/Chat/markdown/url-policy.d.ts +33 -0
- package/dist/components/Chat/markdown/url-policy.js +109 -0
- package/dist/components/FileUpload/FileUpload.svelte +52 -125
- package/dist/components/FileUpload/FileUpload.svelte.d.ts +1 -1
- package/dist/components/FileUpload/index.d.ts +2 -28
- package/dist/components/Planner/PlannerHeader.svelte +16 -13
- package/dist/components/Planner/planner.variants.js +14 -3
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.js +1 -0
- package/dist/i18n/index.d.ts +268 -382
- 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/registry.d.ts +20 -2
- package/dist/mint/registry.js +20 -2
- package/dist/primitives/Badge/Badge.svelte +5 -5
- package/dist/primitives/Badge/badge.variants.js +17 -1
- package/dist/primitives/Button/Button.svelte +4 -2
- package/dist/primitives/Collapsible/Collapsible.svelte +5 -0
- 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/Spinner/Spinner.svelte +3 -1
- package/dist/primitives/SplitPane/SplitPane.svelte +293 -0
- package/dist/primitives/SplitPane/SplitPane.svelte.d.ts +4 -0
- package/dist/primitives/SplitPane/index.d.ts +88 -0
- package/dist/primitives/SplitPane/index.js +2 -0
- package/dist/primitives/SplitPane/split-pane.utils.d.ts +73 -0
- package/dist/primitives/SplitPane/split-pane.utils.js +94 -0
- package/dist/primitives/SplitPane/split-pane.variants.d.ts +40 -0
- package/dist/primitives/SplitPane/split-pane.variants.js +56 -0
- package/dist/primitives/Toast/Toaster.svelte +17 -2
- package/dist/primitives/index.d.ts +2 -0
- package/dist/primitives/index.js +1 -0
- package/dist/utils/file-intake.d.ts +78 -0
- package/dist/utils/file-intake.js +144 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/variants.js +44 -10
- package/package.json +4 -6
package/dist/i18n/index.js
CHANGED
|
@@ -1,13 +1,62 @@
|
|
|
1
1
|
import { createPackageI18n } from '@urbicon-ui/i18n';
|
|
2
|
-
import deTranslations from '../translations/de.js';
|
|
3
2
|
import enTranslations from '../translations/en.js';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
/**
|
|
4
|
+
* blocks package i18n.
|
|
5
|
+
*
|
|
6
|
+
* **Only the English base bundle is eager.** German (`de`) is registered as a
|
|
7
|
+
* lazy dynamic-import loader, so an English-only app never statically bundles the
|
|
8
|
+
* `de` catalog (~4 KB min) — Vite/Rollup splits it into its own chunk that loads
|
|
9
|
+
* only when the `de` locale is activated. `en` is the base/fallback locale.
|
|
10
|
+
*
|
|
11
|
+
* The eager base is `{ en }` (not `blocksTranslations`, which is retained below as
|
|
12
|
+
* an `{ en }` back-compat export). Registration is lazy on first
|
|
13
|
+
* `useBlocksI18n()`/`t()` — see `createPackageI18n`.
|
|
14
|
+
*
|
|
15
|
+
* ## Before the `de` chunk loads: resolution falls back to `en`
|
|
16
|
+
*
|
|
17
|
+
* A package-scoped lookup for a `de` key that isn't loaded yet resolves through
|
|
18
|
+
* the package fallback locale, i.e. it returns the **English** string (verified:
|
|
19
|
+
* `@urbicon-ui/i18n` `registry.translate` package path + `lazy-load.test.ts`). It
|
|
20
|
+
* never renders the raw key. The provider (`<I18nProvider>`) triggers the `de`
|
|
21
|
+
* load in a **client-only** `$effect` on mount, so a `de` app renders English on
|
|
22
|
+
* the server and the first client paint, then re-resolves to German once the
|
|
23
|
+
* chunk lands — a brief text flash and a possible hydration text mismatch.
|
|
24
|
+
* Two consequences of that window worth knowing:
|
|
25
|
+
*
|
|
26
|
+
* - The "falls back to English" guarantee assumes the provider's `fallbackLocale`
|
|
27
|
+
* stays at its default (`en`). Pointing `fallbackLocale` at a lazy locale that
|
|
28
|
+
* has not loaded yet leaves both lookup paths empty — such a key then renders
|
|
29
|
+
* raw and fires `onMissingKey`. Eager-register any locale you use as fallback.
|
|
30
|
+
* - `LocaleSwitcher` disables its trigger while a locale chunk load is in flight
|
|
31
|
+
* (`registry.isLoading`), so without the eager register a `de` app briefly
|
|
32
|
+
* shows the switcher disabled on first mount.
|
|
33
|
+
*
|
|
34
|
+
* The SSR recipe below removes both, along with the flash itself.
|
|
35
|
+
*
|
|
36
|
+
* ## SSR recipe for German (and other non-base) apps
|
|
37
|
+
*
|
|
38
|
+
* German SvelteKit SSR apps should register the `de` bundle eagerly **once at
|
|
39
|
+
* app start** so the very first server render is already German (no flash, no
|
|
40
|
+
* hydration mismatch). The registry is module-global and holds only static,
|
|
41
|
+
* request-identical translation data, so a single startup registration is
|
|
42
|
+
* SSR-safe — it carries no per-request state:
|
|
43
|
+
*
|
|
44
|
+
* ```ts
|
|
45
|
+
* // src/hooks.server.ts (or any module evaluated once at server start)
|
|
46
|
+
* import { registerBlocksLocale } from '@urbicon-ui/blocks';
|
|
47
|
+
* import de from '@urbicon-ui/blocks/i18n/de';
|
|
48
|
+
*
|
|
49
|
+
* registerBlocksLocale('de', de);
|
|
50
|
+
* ```
|
|
51
|
+
*
|
|
52
|
+
* This keeps the `de` catalog out of English-only client bundles (the whole point
|
|
53
|
+
* of the split) while making it eagerly present wherever it is actually rendered.
|
|
54
|
+
*/
|
|
55
|
+
export const blocksI18n = createPackageI18n('blocks', { en: enTranslations }, {
|
|
56
|
+
loaders: {
|
|
57
|
+
de: () => import('../translations/de.js').then((m) => m.default)
|
|
58
|
+
}
|
|
59
|
+
});
|
|
11
60
|
/**
|
|
12
61
|
* Context-scoped translation hook for the blocks package. Call during component
|
|
13
62
|
* initialisation, then use the returned `t` (conventionally aliased `bt`):
|
|
@@ -18,10 +67,35 @@ export const blocksI18n = createPackageI18n('blocks', blocksTranslations);
|
|
|
18
67
|
* ```
|
|
19
68
|
*
|
|
20
69
|
* Resolves against the nearest `<I18nProvider>`'s locale (or the base locale
|
|
21
|
-
* when none is mounted) and re-renders reactively on locale change.
|
|
70
|
+
* when none is mounted) and re-renders reactively on locale change. For a lazy
|
|
71
|
+
* locale (`de`) that isn't loaded yet, resolution falls back to the base locale
|
|
72
|
+
* (`en`); see the module docblock and `registerBlocksLocale` for the SSR path.
|
|
22
73
|
*/
|
|
23
74
|
export const useBlocksI18n = blocksI18n.useTranslate;
|
|
75
|
+
/**
|
|
76
|
+
* Eagerly register the blocks bundle for a lazy locale (currently `de`) so it is
|
|
77
|
+
* present for SSR / the first render, instead of loading client-side on mount.
|
|
78
|
+
* Call once at app/server start, paired with the public locale subpath import:
|
|
79
|
+
*
|
|
80
|
+
* ```ts
|
|
81
|
+
* import { registerBlocksLocale } from '@urbicon-ui/blocks';
|
|
82
|
+
* import de from '@urbicon-ui/blocks/i18n/de';
|
|
83
|
+
* registerBlocksLocale('de', de);
|
|
84
|
+
* ```
|
|
85
|
+
*
|
|
86
|
+
* Additive (does not drop the eager `en` base) and strict (throws on an
|
|
87
|
+
* unsupported locale or a non-object bundle).
|
|
88
|
+
*/
|
|
89
|
+
export const registerBlocksLocale = (locale, bundle) => blocksI18n.registerLocale(locale, bundle);
|
|
24
90
|
// Introspection helpers (locale list / key existence).
|
|
25
91
|
export const { exists: hasBlocksTranslation, getLocales: getBlocksLocales } = blocksI18n;
|
|
92
|
+
/**
|
|
93
|
+
* The eager base bundle only (`{ en }`). `de` is lazy and no longer part of this
|
|
94
|
+
* object; import it explicitly via `@urbicon-ui/blocks/i18n/de` (e.g. for a parity
|
|
95
|
+
* test or the SSR eager-register recipe above).
|
|
96
|
+
*/
|
|
97
|
+
const blocksTranslations = {
|
|
98
|
+
en: enTranslations
|
|
99
|
+
};
|
|
26
100
|
// Re-export for external use
|
|
27
101
|
export { blocksTranslations };
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
CoreIconButton — behaviour-only internal core for the small icon-only controls
|
|
3
|
+
embedded inside other public components (Badge's remove ×, Dialog/Drawer close
|
|
4
|
+
×). It renders a native `<button type="button">` with just the interaction
|
|
5
|
+
baseline (flex-centred content, pointer/select affordance, focus-visible reset,
|
|
6
|
+
disabled inertness). Visual identity — size, radius, colour, ring, shadow — comes
|
|
7
|
+
entirely from the call-site's `class` (a `*.variants.ts` slot), NOT from a variant
|
|
8
|
+
engine pass here: this core deliberately does not touch tv()/mint/tokens, which is
|
|
9
|
+
what lets a public component embed a control without importing another public
|
|
10
|
+
component (keeps the public-to-public import graph clean, see internal/core/).
|
|
11
|
+
|
|
12
|
+
The base classes are structural plumbing, deliberately NOT tw-merged against the
|
|
13
|
+
incoming `class` (no engine here): a consumer slot class targeting one of these
|
|
14
|
+
buckets (display/cursor/select/disabled-opacity) is resolved by stylesheet order,
|
|
15
|
+
not by the override ladder. That is accepted: overrides belong on the call-site's
|
|
16
|
+
variants slot (which merges correctly bucket-by-bucket); the plumbing is not an
|
|
17
|
+
override surface. Under `unstyled` the plumbing also stays — stripping
|
|
18
|
+
`disabled:pointer-events-none` & co. would break behaviour, not styling.
|
|
19
|
+
|
|
20
|
+
INTERNAL — never exported from the package barrel, no docs/MCP entry. For a full
|
|
21
|
+
themed button use the public `Button`.
|
|
22
|
+
|
|
23
|
+
restProps-first spread (COMPONENT-API-CONVENTIONS §restProps ordering): the
|
|
24
|
+
explicit attributes come AFTER `{...restProps}` so component-owned wiring wins —
|
|
25
|
+
`aria-label` is required (an icon-only button has no text accessible name) and
|
|
26
|
+
can never be clobbered, and `type="button"` stays a submit-safe default.
|
|
27
|
+
-->
|
|
28
|
+
<script lang="ts">
|
|
29
|
+
import type { Snippet } from 'svelte';
|
|
30
|
+
import type { HTMLButtonAttributes } from 'svelte/elements';
|
|
31
|
+
|
|
32
|
+
let {
|
|
33
|
+
'aria-label': ariaLabel,
|
|
34
|
+
class: className = '',
|
|
35
|
+
disabled = false,
|
|
36
|
+
onclick,
|
|
37
|
+
children,
|
|
38
|
+
...restProps
|
|
39
|
+
}: {
|
|
40
|
+
/** Required — an icon-only control has no text to name it. */
|
|
41
|
+
'aria-label': string;
|
|
42
|
+
class?: string;
|
|
43
|
+
disabled?: boolean;
|
|
44
|
+
onclick?: (event: MouseEvent) => void;
|
|
45
|
+
children: Snippet;
|
|
46
|
+
} & Omit<
|
|
47
|
+
HTMLButtonAttributes,
|
|
48
|
+
'aria-label' | 'class' | 'disabled' | 'onclick' | 'children'
|
|
49
|
+
> = $props();
|
|
50
|
+
</script>
|
|
51
|
+
|
|
52
|
+
<button
|
|
53
|
+
{...restProps}
|
|
54
|
+
type="button"
|
|
55
|
+
{disabled}
|
|
56
|
+
{onclick}
|
|
57
|
+
aria-label={ariaLabel}
|
|
58
|
+
class={[
|
|
59
|
+
'inline-flex items-center justify-center cursor-pointer select-none',
|
|
60
|
+
'focus-visible:outline-none',
|
|
61
|
+
'disabled:opacity-50 disabled:cursor-not-allowed disabled:pointer-events-none',
|
|
62
|
+
className
|
|
63
|
+
]}
|
|
64
|
+
>
|
|
65
|
+
{@render children()}
|
|
66
|
+
</button>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLButtonAttributes } from 'svelte/elements';
|
|
3
|
+
type $$ComponentProps = {
|
|
4
|
+
/** Required — an icon-only control has no text to name it. */
|
|
5
|
+
'aria-label': string;
|
|
6
|
+
class?: string;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
onclick?: (event: MouseEvent) => void;
|
|
9
|
+
children: Snippet;
|
|
10
|
+
} & Omit<HTMLButtonAttributes, 'aria-label' | 'class' | 'disabled' | 'onclick' | 'children'>;
|
|
11
|
+
declare const CoreIconButton: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
12
|
+
type CoreIconButton = ReturnType<typeof CoreIconButton>;
|
|
13
|
+
export default CoreIconButton;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
CoreSpinner — the bare rotating-arc SVG shared by embedding contexts (loading
|
|
3
|
+
Button, and any internal surface that needs an inline busy indicator) WITHOUT
|
|
4
|
+
pulling in the public Spinner.
|
|
5
|
+
|
|
6
|
+
INTERNAL — never exported from the package barrel, no docs/MCP entry. For a
|
|
7
|
+
configurable spinner (variants, speed, intent palette, sr-only label, unstyled
|
|
8
|
+
/ slotClasses) use the public `Spinner`; this core is deliberately fixed to the
|
|
9
|
+
default variant at 1s.
|
|
10
|
+
|
|
11
|
+
No `role` / `aria-*` / sr-only label here on purpose: the embedding context
|
|
12
|
+
owns the semantics. Button wraps this in an `aria-hidden` span and announces
|
|
13
|
+
loading via its own `aria-busy`; a `role="status"` here would nest a live
|
|
14
|
+
region inside contexts that already declare one (e.g. Toast). The geometry is
|
|
15
|
+
imported from `spinner-geometry.ts` so it can never drift from the public
|
|
16
|
+
Spinner.
|
|
17
|
+
-->
|
|
18
|
+
<script lang="ts">
|
|
19
|
+
import { SPINNER_ARC_PATH } from './spinner-geometry';
|
|
20
|
+
|
|
21
|
+
let {
|
|
22
|
+
size = 'md',
|
|
23
|
+
class: className = ''
|
|
24
|
+
}: {
|
|
25
|
+
size?: 'xs' | 'sm' | 'md' | 'lg';
|
|
26
|
+
/** Extra classes on the wrapper span (the call site supplies visual identity). */
|
|
27
|
+
class?: string;
|
|
28
|
+
} = $props();
|
|
29
|
+
|
|
30
|
+
// Matches the public Spinner's per-size box (spinner.variants → base sizes).
|
|
31
|
+
const sizeClass = {
|
|
32
|
+
xs: 'w-4 h-4',
|
|
33
|
+
sm: 'w-5 h-5',
|
|
34
|
+
md: 'w-6 h-6',
|
|
35
|
+
lg: 'w-8 h-8'
|
|
36
|
+
};
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<span class={['inline-flex items-center justify-center text-current', sizeClass[size], className]}>
|
|
40
|
+
<svg
|
|
41
|
+
class="w-full h-full animate-spin [animation-duration:1s] motion-reduce:animate-none"
|
|
42
|
+
viewBox="0 0 24 24"
|
|
43
|
+
fill="none"
|
|
44
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
45
|
+
>
|
|
46
|
+
<circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" class="opacity-25" />
|
|
47
|
+
<path class="fill-current" d={SPINNER_ARC_PATH} />
|
|
48
|
+
</svg>
|
|
49
|
+
</span>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
type $$ComponentProps = {
|
|
2
|
+
size?: 'xs' | 'sm' | 'md' | 'lg';
|
|
3
|
+
/** Extra classes on the wrapper span (the call site supplies visual identity). */
|
|
4
|
+
class?: string;
|
|
5
|
+
};
|
|
6
|
+
declare const CoreSpinner: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
7
|
+
type CoreSpinner = ReturnType<typeof CoreSpinner>;
|
|
8
|
+
export default CoreSpinner;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* single source of the spinner geometry — imported by CoreSpinner and the
|
|
3
|
+
* public Spinner. The `d` attribute of the rotating arc `<path>` in the
|
|
4
|
+
* default (spinner) variant. Kept in one place so the two SVGs never drift.
|
|
5
|
+
*/
|
|
6
|
+
export declare const SPINNER_ARC_PATH = "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* single source of the spinner geometry — imported by CoreSpinner and the
|
|
3
|
+
* public Spinner. The `d` attribute of the rotating arc `<path>` in the
|
|
4
|
+
* default (spinner) variant. Kept in one place so the two SVGs never drift.
|
|
5
|
+
*/
|
|
6
|
+
export const SPINNER_ARC_PATH = 'M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z';
|
package/dist/mint/registry.d.ts
CHANGED
|
@@ -47,15 +47,33 @@ declare class MintRegistry {
|
|
|
47
47
|
* effect. Acceptable for decorative effects (documented contract, see
|
|
48
48
|
* mint/README.md); consumers who need first-interaction guarantees register
|
|
49
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.
|
|
50
56
|
*/
|
|
51
57
|
apply(el: HTMLElement, mint: MintProp, fallbacks?: MintFallbacks): () => void;
|
|
52
58
|
/** Normalize polymorphic mint prop to consistent format */
|
|
53
59
|
private normalizeMintProp;
|
|
54
|
-
/**
|
|
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
|
+
*/
|
|
55
67
|
update(el: HTMLElement, name: string, config: MintConfig): void;
|
|
56
68
|
/** List all registered mint names */
|
|
57
69
|
list(): string[];
|
|
58
|
-
/**
|
|
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
|
+
*/
|
|
59
77
|
clear(): void;
|
|
60
78
|
}
|
|
61
79
|
export declare const mintRegistry: MintRegistry;
|
package/dist/mint/registry.js
CHANGED
|
@@ -59,6 +59,12 @@ class MintRegistry {
|
|
|
59
59
|
* effect. Acceptable for decorative effects (documented contract, see
|
|
60
60
|
* mint/README.md); consumers who need first-interaction guarantees register
|
|
61
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.
|
|
62
68
|
*/
|
|
63
69
|
apply(el, mint, fallbacks) {
|
|
64
70
|
const mintDefinitions = this.normalizeMintProp(mint);
|
|
@@ -123,7 +129,13 @@ class MintRegistry {
|
|
|
123
129
|
}
|
|
124
130
|
return [];
|
|
125
131
|
}
|
|
126
|
-
/**
|
|
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
|
+
*/
|
|
127
139
|
update(el, name, config) {
|
|
128
140
|
const elementMints = this.instances.get(el);
|
|
129
141
|
const mint = elementMints?.get(name);
|
|
@@ -135,7 +147,13 @@ class MintRegistry {
|
|
|
135
147
|
list() {
|
|
136
148
|
return Array.from(this.mints.keys());
|
|
137
149
|
}
|
|
138
|
-
/**
|
|
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
|
+
*/
|
|
139
157
|
clear() {
|
|
140
158
|
this.mints.clear();
|
|
141
159
|
}
|
|
@@ -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,7 @@
|
|
|
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';
|
|
3
5
|
// Direct import (not the barrel): the resolveIcon tree-shaking pattern.
|
|
4
6
|
// Button's mint default is 'scale', so the scale factory ships statically
|
|
5
7
|
// as the apply() fallback; every other mint name stays demand-loaded.
|
|
@@ -154,7 +156,7 @@
|
|
|
154
156
|
: styles.spinner({ class: slotClasses?.spinner })}
|
|
155
157
|
aria-hidden="true"
|
|
156
158
|
>
|
|
157
|
-
<
|
|
159
|
+
<CoreSpinner size={spinnerSizeMap[effectiveSize]} />
|
|
158
160
|
</span>
|
|
159
161
|
|
|
160
162
|
<span
|
|
@@ -109,10 +109,15 @@
|
|
|
109
109
|
</button>
|
|
110
110
|
{/if}
|
|
111
111
|
|
|
112
|
+
<!-- `inert` while collapsed (Popover's pattern): the clipped children stay
|
|
113
|
+
mounted for the grid-rows animation, so without it a keyboard user tabs
|
|
114
|
+
into invisible controls (e.g. a CodeBlock copy button inside a collapsed
|
|
115
|
+
ToolCallCard — WCAG 2.4.3/2.4.7) and the subtree stays in the a11y tree. -->
|
|
112
116
|
<div
|
|
113
117
|
id={contentId}
|
|
114
118
|
role="region"
|
|
115
119
|
aria-labelledby={triggerId}
|
|
120
|
+
inert={!isOpen}
|
|
116
121
|
class={unstyled
|
|
117
122
|
? (slotClasses?.content ?? '')
|
|
118
123
|
: styles.content({ class: slotClasses?.content })}
|
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
import { trapFocus, showDialogModal, closeDialogModal } from '../../utils/overlay';
|
|
9
9
|
import { composeHandlers } from '../../utils/compose-handlers';
|
|
10
10
|
import { overlayStack, getOverlayMotion } from '../../utils';
|
|
11
|
-
import
|
|
11
|
+
// internal core, not the public component — keeps the public-to-public import graph clean (see internal/core/)
|
|
12
|
+
import CoreIconButton from '../../internal/core/CoreIconButton.svelte';
|
|
12
13
|
import type { DialogProps } from './index';
|
|
13
14
|
import { dialogVariants, type DialogVariants } from './dialog.variants';
|
|
14
15
|
|
|
@@ -316,14 +317,15 @@
|
|
|
316
317
|
{title}
|
|
317
318
|
</h2>
|
|
318
319
|
{#if !hideCloseButton}
|
|
319
|
-
<
|
|
320
|
-
|
|
321
|
-
|
|
320
|
+
<CoreIconButton
|
|
321
|
+
class={unstyled
|
|
322
|
+
? (slotClasses?.closeButton ?? '')
|
|
323
|
+
: styles.closeButton({ class: slotClasses?.closeButton })}
|
|
322
324
|
onclick={requestClose}
|
|
323
325
|
aria-label={bt('accessibility.closeDialog')}
|
|
324
326
|
>
|
|
325
327
|
<CloseIcon class="h-4 w-4" />
|
|
326
|
-
</
|
|
328
|
+
</CoreIconButton>
|
|
327
329
|
{/if}
|
|
328
330
|
</header>
|
|
329
331
|
|
|
@@ -46,6 +46,13 @@ export declare const dialogVariants: ((props?: {
|
|
|
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
|
+
closeButton: (props?: ({
|
|
50
|
+
size?: "sm" | "md" | "lg" | "xl" | "fullscreen" | "full" | undefined;
|
|
51
|
+
placement?: "top" | "center" | undefined;
|
|
52
|
+
intent?: "primary" | "secondary" | "success" | "warning" | "danger" | "neutral" | undefined;
|
|
53
|
+
} & {
|
|
54
|
+
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;
|
|
55
|
+
}) | undefined) => string;
|
|
49
56
|
body: (props?: ({
|
|
50
57
|
size?: "sm" | "md" | "lg" | "xl" | "fullscreen" | "full" | undefined;
|
|
51
58
|
placement?: "top" | "center" | undefined;
|
|
@@ -26,6 +26,23 @@ export const dialogVariants = tv({
|
|
|
26
26
|
'border-b border-border-hairline flex-shrink-0'
|
|
27
27
|
],
|
|
28
28
|
title: ['text-base font-semibold text-text-primary truncate'],
|
|
29
|
+
// Icon-only header close control (× dismiss). Rendered on the internal
|
|
30
|
+
// CoreIconButton (behaviour-only base: inline-flex centring, cursor/select,
|
|
31
|
+
// focus-visible reset, disabled inertness), so this slot carries the FULL
|
|
32
|
+
// visual identity of the `<Button variant="ghost" size="sm">` (intent
|
|
33
|
+
// neutral, tier commit) it used to be — the exact ghost/sm neutral Button
|
|
34
|
+
// fold MINUS the classes CoreIconButton already supplies. Effective render is
|
|
35
|
+
// byte-identical to the pre-extraction close button (no VR baseline gates
|
|
36
|
+
// overlays; reproduced deterministically from buttonVariants). See
|
|
37
|
+
// internal/core/.
|
|
38
|
+
closeButton: [
|
|
39
|
+
'relative font-medium text-center whitespace-nowrap border overflow-hidden',
|
|
40
|
+
'transition-[color,background-color,border-color,box-shadow,opacity,transform] duration-[var(--blocks-duration-fast)] ease-out',
|
|
41
|
+
'rounded-commit bg-transparent border-transparent shadow-none',
|
|
42
|
+
'hover:shadow-[var(--blocks-shadow-md)] active:scale-[0.98] active:shadow-[var(--blocks-shadow-sm)]',
|
|
43
|
+
'h-8 px-3 text-sm gap-1.5 text-neutral-emphasis hover:bg-neutral-subtle',
|
|
44
|
+
'focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-neutral/50'
|
|
45
|
+
],
|
|
29
46
|
body: [
|
|
30
47
|
'px-5 py-4 flex-1 overflow-y-auto overscroll-contain',
|
|
31
48
|
'text-sm leading-relaxed text-text-secondary'
|
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
import { trapFocus, showDialogModal, closeDialogModal } from '../../utils/overlay';
|
|
9
9
|
import { composeHandlers } from '../../utils/compose-handlers';
|
|
10
10
|
import { overlayStack, getOverlayMotion } from '../../utils';
|
|
11
|
-
import
|
|
11
|
+
// internal core, not the public component — keeps the public-to-public import graph clean (see internal/core/)
|
|
12
|
+
import CoreIconButton from '../../internal/core/CoreIconButton.svelte';
|
|
12
13
|
import type { DrawerProps } from './index';
|
|
13
14
|
import { drawerVariants, type DrawerVariants } from './drawer.variants';
|
|
14
15
|
|
|
@@ -252,14 +253,15 @@
|
|
|
252
253
|
<span></span>
|
|
253
254
|
{/if}
|
|
254
255
|
{#if !hideCloseButton}
|
|
255
|
-
<
|
|
256
|
-
|
|
257
|
-
|
|
256
|
+
<CoreIconButton
|
|
257
|
+
class={unstyled
|
|
258
|
+
? (slotClasses?.closeButton ?? '')
|
|
259
|
+
: styles.closeButton({ class: slotClasses?.closeButton })}
|
|
258
260
|
onclick={requestClose}
|
|
259
261
|
aria-label={bt('accessibility.closeDrawer')}
|
|
260
262
|
>
|
|
261
263
|
<CloseIcon class="h-4 w-4" />
|
|
262
|
-
</
|
|
264
|
+
</CoreIconButton>
|
|
263
265
|
{/if}
|
|
264
266
|
</header>
|
|
265
267
|
{/if}
|
|
@@ -45,6 +45,14 @@ export declare const drawerVariants: ((props?: {
|
|
|
45
45
|
} & {
|
|
46
46
|
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;
|
|
47
47
|
}) | undefined) => string;
|
|
48
|
+
closeButton: (props?: ({
|
|
49
|
+
placement?: "top" | "right" | "bottom" | "left" | undefined;
|
|
50
|
+
size?: "sm" | "md" | "lg" | "xl" | "full" | undefined;
|
|
51
|
+
intent?: "primary" | "secondary" | "success" | "warning" | "danger" | "neutral" | undefined;
|
|
52
|
+
accentEdge?: boolean | undefined;
|
|
53
|
+
} & {
|
|
54
|
+
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;
|
|
55
|
+
}) | undefined) => string;
|
|
48
56
|
body: (props?: ({
|
|
49
57
|
placement?: "top" | "right" | "bottom" | "left" | undefined;
|
|
50
58
|
size?: "sm" | "md" | "lg" | "xl" | "full" | undefined;
|
|
@@ -18,6 +18,23 @@ export const drawerVariants = tv({
|
|
|
18
18
|
'border-b border-border-hairline flex-shrink-0'
|
|
19
19
|
],
|
|
20
20
|
title: ['text-base font-semibold text-text-primary truncate'],
|
|
21
|
+
// Icon-only header close control (× dismiss). Rendered on the internal
|
|
22
|
+
// CoreIconButton (behaviour-only base: inline-flex centring, cursor/select,
|
|
23
|
+
// focus-visible reset, disabled inertness), so this slot carries the FULL
|
|
24
|
+
// visual identity of the `<Button variant="ghost" size="sm">` (intent
|
|
25
|
+
// neutral, tier commit) it used to be — the exact ghost/sm neutral Button
|
|
26
|
+
// fold MINUS the classes CoreIconButton already supplies. Effective render is
|
|
27
|
+
// byte-identical to the pre-extraction close button (no VR baseline gates
|
|
28
|
+
// overlays; reproduced deterministically from buttonVariants). Mirrors Dialog.
|
|
29
|
+
// See internal/core/.
|
|
30
|
+
closeButton: [
|
|
31
|
+
'relative font-medium text-center whitespace-nowrap border overflow-hidden',
|
|
32
|
+
'transition-[color,background-color,border-color,box-shadow,opacity,transform] duration-[var(--blocks-duration-fast)] ease-out',
|
|
33
|
+
'rounded-commit bg-transparent border-transparent shadow-none',
|
|
34
|
+
'hover:shadow-[var(--blocks-shadow-md)] active:scale-[0.98] active:shadow-[var(--blocks-shadow-sm)]',
|
|
35
|
+
'h-8 px-3 text-sm gap-1.5 text-neutral-emphasis hover:bg-neutral-subtle',
|
|
36
|
+
'focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-neutral/50'
|
|
37
|
+
],
|
|
21
38
|
body: [
|
|
22
39
|
'px-5 py-4 flex-1 overflow-y-auto overscroll-contain',
|
|
23
40
|
'text-sm leading-relaxed text-text-secondary'
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { getBlocksConfig, resolveSlotClasses } from '../../provider';
|
|
3
|
+
// internal core, not the public component — keeps the public-to-public import graph clean (see internal/core/)
|
|
4
|
+
import { SPINNER_ARC_PATH } from '../../internal/core/spinner-geometry';
|
|
3
5
|
import { spinnerVariants, type SpinnerVariants } from './spinner.variants';
|
|
4
6
|
import type { SpinnerProps } from './index';
|
|
5
7
|
|
|
@@ -126,7 +128,7 @@
|
|
|
126
128
|
class={unstyled
|
|
127
129
|
? (slotClasses?.svgPath ?? '')
|
|
128
130
|
: styles.svgPath({ class: slotClasses?.svgPath })}
|
|
129
|
-
d=
|
|
131
|
+
d={SPINNER_ARC_PATH}
|
|
130
132
|
/>
|
|
131
133
|
</svg>
|
|
132
134
|
{/if}
|