entasis 0.13.6 → 0.13.8
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/dist/components/Form/Form/form.state.svelte.d.ts +4 -0
- package/dist/components/Form/Form/visibility.d.ts +2 -0
- package/dist/components/Form/MultiStepForm/multiStepForm.state.svelte.d.ts +4 -0
- package/dist/components/Form/SignatureInput/SignatureInput.svelte +39 -1
- package/dist/components/Form/SignatureInput/index.d.ts +1 -1
- package/dist/components/Form/SignatureInput/signatureInput.mcp.d.ts +1 -1
- package/dist/components/Form/SignatureInput/signatureInput.mcp.js +1 -0
- package/dist/components/Form/SignatureInput/signatureInput.props.d.ts +9 -0
- package/dist/components/Form/SignatureInput/signatureInput.theme.d.ts +18 -3
- package/dist/components/Form/SignatureInput/signatureInput.theme.js +13 -2
- package/dist/components/Sidebar/Sidebar.svelte +1 -1
- package/dist/components/Sidebar/SidebarMenuItem.svelte +59 -15
- package/dist/components/Sidebar/SidebarMenuSubItem.svelte +43 -12
- package/dist/components/Sidebar/SidebarMenuText.svelte +60 -0
- package/dist/components/Sidebar/SidebarMenuText.svelte.d.ts +18 -0
- package/dist/components/Sidebar/sidebar.mcp.d.ts +1 -1
- package/dist/components/Sidebar/sidebar.mcp.js +53 -0
- package/dist/components/Sidebar/sidebar.props.d.ts +31 -0
- package/dist/components/Sidebar/sidebar.theme.d.ts +99 -0
- package/dist/components/Sidebar/sidebar.theme.js +100 -9
- package/dist/generated/componentContract.d.ts +1 -1
- package/dist/generated/componentContract.js +1 -0
- package/package.json +1 -1
|
@@ -527,6 +527,7 @@ export declare class FormState<I extends FormInputs = FormInputs> {
|
|
|
527
527
|
} & Omit<import("../Field/field.js").InputProps<"signature">, "theme"> & {
|
|
528
528
|
format?: import("../SignatureInput/signatureInput.strokes.ts").SignatureFormat;
|
|
529
529
|
inkColor?: string;
|
|
530
|
+
imageInk?: import("../SignatureInput/signatureInput.props.ts").SignatureImageInk;
|
|
530
531
|
strokeWidth?: number;
|
|
531
532
|
placeholder?: string;
|
|
532
533
|
clearLabel?: string;
|
|
@@ -1412,6 +1413,7 @@ export declare class FormState<I extends FormInputs = FormInputs> {
|
|
|
1412
1413
|
} & Omit<import("../Field/field.js").InputProps<"signature">, "theme"> & {
|
|
1413
1414
|
format?: import("../SignatureInput/signatureInput.strokes.ts").SignatureFormat;
|
|
1414
1415
|
inkColor?: string;
|
|
1416
|
+
imageInk?: import("../SignatureInput/signatureInput.props.ts").SignatureImageInk;
|
|
1415
1417
|
strokeWidth?: number;
|
|
1416
1418
|
placeholder?: string;
|
|
1417
1419
|
clearLabel?: string;
|
|
@@ -2493,6 +2495,7 @@ export declare class FormState<I extends FormInputs = FormInputs> {
|
|
|
2493
2495
|
} & Omit<import("../Field/field.js").InputProps<"signature">, "theme"> & {
|
|
2494
2496
|
format?: import("../SignatureInput/signatureInput.strokes.ts").SignatureFormat;
|
|
2495
2497
|
inkColor?: string;
|
|
2498
|
+
imageInk?: import("../SignatureInput/signatureInput.props.ts").SignatureImageInk;
|
|
2496
2499
|
strokeWidth?: number;
|
|
2497
2500
|
placeholder?: string;
|
|
2498
2501
|
clearLabel?: string;
|
|
@@ -3378,6 +3381,7 @@ export declare class FormState<I extends FormInputs = FormInputs> {
|
|
|
3378
3381
|
} & Omit<import("../Field/field.js").InputProps<"signature">, "theme"> & {
|
|
3379
3382
|
format?: import("../SignatureInput/signatureInput.strokes.ts").SignatureFormat;
|
|
3380
3383
|
inkColor?: string;
|
|
3384
|
+
imageInk?: import("../SignatureInput/signatureInput.props.ts").SignatureImageInk;
|
|
3381
3385
|
strokeWidth?: number;
|
|
3382
3386
|
placeholder?: string;
|
|
3383
3387
|
clearLabel?: string;
|
|
@@ -1400,6 +1400,7 @@ export declare function prepareInputProps(input: FormFieldInput, size: Sizes, la
|
|
|
1400
1400
|
format?: import("../SignatureInput/signatureInput.strokes.ts").SignatureFormat | undefined;
|
|
1401
1401
|
clearLabel?: string | undefined;
|
|
1402
1402
|
inkColor?: string | undefined;
|
|
1403
|
+
imageInk?: import("../SignatureInput/signatureInput.props.ts").SignatureImageInk | undefined;
|
|
1403
1404
|
strokeWidth?: number | undefined;
|
|
1404
1405
|
undoLabel?: string | undefined;
|
|
1405
1406
|
display?: string;
|
|
@@ -7755,6 +7756,7 @@ export declare function prepareInputProps(input: FormFieldInput, size: Sizes, la
|
|
|
7755
7756
|
format?: import("../SignatureInput/signatureInput.strokes.ts").SignatureFormat | undefined;
|
|
7756
7757
|
clearLabel?: string | undefined;
|
|
7757
7758
|
inkColor?: string | undefined;
|
|
7759
|
+
imageInk?: import("../SignatureInput/signatureInput.props.ts").SignatureImageInk | undefined;
|
|
7758
7760
|
strokeWidth?: number | undefined;
|
|
7759
7761
|
undoLabel?: string | undefined;
|
|
7760
7762
|
display?: string;
|
|
@@ -442,6 +442,7 @@ export declare class MultiStepFormState<I extends MultiStepFormItems = FormStep[
|
|
|
442
442
|
} & Omit<import("../Field/field.ts").InputProps<"signature">, "theme"> & {
|
|
443
443
|
format?: import("../SignatureInput/signatureInput.strokes.ts").SignatureFormat;
|
|
444
444
|
inkColor?: string;
|
|
445
|
+
imageInk?: import("../SignatureInput/signatureInput.props.ts").SignatureImageInk;
|
|
445
446
|
strokeWidth?: number;
|
|
446
447
|
placeholder?: string;
|
|
447
448
|
clearLabel?: string;
|
|
@@ -1327,6 +1328,7 @@ export declare class MultiStepFormState<I extends MultiStepFormItems = FormStep[
|
|
|
1327
1328
|
} & Omit<import("../Field/field.ts").InputProps<"signature">, "theme"> & {
|
|
1328
1329
|
format?: import("../SignatureInput/signatureInput.strokes.ts").SignatureFormat;
|
|
1329
1330
|
inkColor?: string;
|
|
1331
|
+
imageInk?: import("../SignatureInput/signatureInput.props.ts").SignatureImageInk;
|
|
1330
1332
|
strokeWidth?: number;
|
|
1331
1333
|
placeholder?: string;
|
|
1332
1334
|
clearLabel?: string;
|
|
@@ -2408,6 +2410,7 @@ export declare class MultiStepFormState<I extends MultiStepFormItems = FormStep[
|
|
|
2408
2410
|
} & Omit<import("../Field/field.ts").InputProps<"signature">, "theme"> & {
|
|
2409
2411
|
format?: import("../SignatureInput/signatureInput.strokes.ts").SignatureFormat;
|
|
2410
2412
|
inkColor?: string;
|
|
2413
|
+
imageInk?: import("../SignatureInput/signatureInput.props.ts").SignatureImageInk;
|
|
2411
2414
|
strokeWidth?: number;
|
|
2412
2415
|
placeholder?: string;
|
|
2413
2416
|
clearLabel?: string;
|
|
@@ -3293,6 +3296,7 @@ export declare class MultiStepFormState<I extends MultiStepFormItems = FormStep[
|
|
|
3293
3296
|
} & Omit<import("../Field/field.ts").InputProps<"signature">, "theme"> & {
|
|
3294
3297
|
format?: import("../SignatureInput/signatureInput.strokes.ts").SignatureFormat;
|
|
3295
3298
|
inkColor?: string;
|
|
3299
|
+
imageInk?: import("../SignatureInput/signatureInput.props.ts").SignatureImageInk;
|
|
3296
3300
|
strokeWidth?: number;
|
|
3297
3301
|
placeholder?: string;
|
|
3298
3302
|
clearLabel?: string;
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
size = 'normal',
|
|
34
34
|
format = 'png',
|
|
35
35
|
inkColor = '#000000',
|
|
36
|
+
imageInk = 'theme',
|
|
36
37
|
strokeWidth = 2.5,
|
|
37
38
|
placeholder,
|
|
38
39
|
clearLabel,
|
|
@@ -125,6 +126,27 @@
|
|
|
125
126
|
|
|
126
127
|
const hasInk = $derived(strokes.length > 0 || current !== null);
|
|
127
128
|
const image = $derived(hasInk ? null : (field.value ?? null));
|
|
129
|
+
|
|
130
|
+
// A mask image is fetched in CORS mode: a URL from another origin that does not allow it would
|
|
131
|
+
// paint nothing. Such a URL is probed once and, when refused, shown as the image itself.
|
|
132
|
+
let refusedMask = $state<string | null>(null);
|
|
133
|
+
const ownsImage = (url: string) =>
|
|
134
|
+
/^(data|blob):/.test(url) || new URL(url, location.href).origin === location.origin;
|
|
135
|
+
$effect(() => {
|
|
136
|
+
if (imageInk !== 'theme' || !image || ownsImage(image)) return;
|
|
137
|
+
const probe = new Image();
|
|
138
|
+
probe.crossOrigin = 'anonymous';
|
|
139
|
+
probe.onerror = () => (refusedMask = image);
|
|
140
|
+
probe.src = image;
|
|
141
|
+
return () => {
|
|
142
|
+
probe.onerror = null;
|
|
143
|
+
};
|
|
144
|
+
});
|
|
145
|
+
const imageMode = $derived(imageInk === 'theme' && refusedMask !== image ? 'theme' : 'as-is');
|
|
146
|
+
// Quoted for `url()`: a data URL may hold characters CSS would end the string on.
|
|
147
|
+
const maskImage = $derived(
|
|
148
|
+
image ? `url("${image.replace(/["\\\n]/g, (char) => encodeURIComponent(char))}")` : undefined
|
|
149
|
+
);
|
|
128
150
|
const shapes = $derived(
|
|
129
151
|
[...strokes, ...(current ? [current] : [])].flatMap((stroke) =>
|
|
130
152
|
strokeShapes(stroke, strokeWidth)
|
|
@@ -277,7 +299,23 @@
|
|
|
277
299
|
</div>
|
|
278
300
|
{/if}
|
|
279
301
|
{#if image}
|
|
280
|
-
|
|
302
|
+
{#if imageMode === 'theme'}
|
|
303
|
+
<span
|
|
304
|
+
data-slot="signature-image"
|
|
305
|
+
data-ink="theme"
|
|
306
|
+
class={classes.image({ ink: 'theme' })}
|
|
307
|
+
style:mask-image={maskImage}
|
|
308
|
+
style:-webkit-mask-image={maskImage}
|
|
309
|
+
></span>
|
|
310
|
+
{:else}
|
|
311
|
+
<img
|
|
312
|
+
data-slot="signature-image"
|
|
313
|
+
data-ink="as-is"
|
|
314
|
+
src={image}
|
|
315
|
+
alt=""
|
|
316
|
+
class={classes.image({ ink: 'as-is' })}
|
|
317
|
+
/>
|
|
318
|
+
{/if}
|
|
281
319
|
{/if}
|
|
282
320
|
<svg data-slot="signature-ink" class={classes.ink()} aria-hidden="true" focusable="false">
|
|
283
321
|
<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round">
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { default as SignatureInput } from './SignatureInput.svelte';
|
|
2
|
-
export type { SignatureInputProps } from './signatureInput.props.js';
|
|
2
|
+
export type { SignatureImageInk, SignatureInputProps } from './signatureInput.props.js';
|
|
3
3
|
export type { SignatureFormat, SignaturePoint, SignatureStroke } from './signatureInput.strokes.js';
|
|
4
4
|
export { signatureInputTheme, setSignatureInputTheme, useSignatureInputTheme, type SignatureInputTheme, type SignatureInputThemeProps } from './signatureInput.theme.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const signatureInputDescription = "\n# SignatureInput Component\n\nSignatureInput is a form field where a person signs with a mouse, a finger or a pen. Its value is the signature as an image: a data URL cropped to the ink (PNG by default, or SVG), ready to store, submit or place in a document.\n\n## Basic usage\n\n```svelte\n<script lang=\"ts\">\n import { SignatureInput } from './index.ts';\n\n let signature = $state<string | null>(null);\n</script>\n\n<SignatureInput label=\"Signature\" required bind:value={signature} />\n```\n\nIn a Form or `ask()`, use `type: 'signature'`:\n\n```ts\nimport { ask } from 'entasis/ask';\n\nconst result = await ask({\n title: 'Sign the mandate',\n inputs: { signature: { type: 'signature', label: 'Signature', required: true } },\n confirm: 'Sign',\n cancel: 'Cancel'\n});\n```\n\n## Props\n\nExtends the shared Field props (`label`, `description`, `helper`, `required`, `disabled`, `readOnly`, `name`, `size`, `density`, `labelPosition`, `messages`, `onValidate`, `errors`, `focused`, `visible`) plus:\n\n- **value**: `string | null` (bindable) \u2014 the signature as a data URL, or `null` while the pad is empty.\n- **defaultValue**: `string | null` \u2014 initial value when `value` is omitted. Any image data URL works: a saved signature shows in the pad, scaled to fit.\n- **onValueChange**: `(value: string | null) => void` \u2014 called once per finished stroke, undo and clear.\n- **format**: `'png' | 'svg'` (default `'png'`) \u2014 the image the value holds. A PNG is drawn at twice the pad's resolution; an SVG keeps every stroke as a vector path.\n- **inkColor**: `string` (default `'#000000'`) \u2014 CSS color of the ink in the exported image, so a signature reads on a white document whatever the app's theme. The pad itself draws in the theme's text color.\n- **strokeWidth**: `number` (default `2.5`) \u2014 line width in CSS pixels at a medium pen pressure. A pen's pressure makes the line thinner or thicker (half to one and a half times); a mouse or a finger draws at this width.\n- **placeholder**: `string` \u2014 hint on the signing line while the pad is empty. Defaults to the i18n `signatureInputPlaceholder` (\"Sign here\").\n- **clearLabel**, **undoLabel**: `string` \u2014 accessible labels and tooltips of the two buttons.\n- **i18n**: `Partial<Messages>` \u2014 per-instance translations.\n- **size**: `'small' | 'normal' | 'large'` \u2014 pad height (112, 144 or 176 px) and placeholder text size. Override the height with the `pad` theme part.\n- **theme**: `SignatureInputThemeProps` and Field theme parts.\n\n## Behaviour\n\n- Each stroke runs from pointer down to pointer up and is smoothed through its samples. The value updates when a stroke ends, not while it is drawn.\n- The undo button (or Ctrl/Cmd+Z on the pad) removes the last stroke; the clear button (or Delete/Backspace on the pad) empties the pad and sets the value to `null`. Both show only while the pad is editable and has a signature.\n- A value set from outside (a saved signature, a Form reset) replaces the strokes and shows as an image. Drawing over it starts a new signature: the image is replaced, not added to. Undo only steps back through strokes drawn since.\n- `disabled` and `readOnly` stop drawing and hide the buttons; a read-only pad still shows, focuses, validates and submits its value. A stroke in progress is dropped when the pad becomes disabled or read-only.\n- Required: an empty pad (`null` or `''`) fails `required`.\n- Native forms: a hidden input (`FieldHiddenInputs`) submits the data URL under `name`.\n\n## Accessibility\n\n- The pad is the field's control: it is focusable, labelled by the field label (or \"Signature\" without one), and has `role=\"img\"` with a description of its state (\"No signature yet\u2026\" or \"Signed.\"). Errors and descriptions are linked by Field.\n- Drawing is a path-based gesture with no keyboard equivalent: signing by hand is the purpose of the field. Keyboard users can clear and undo with the buttons and keys above. When a keyboard-only path to consent is needed, pair the pad with another field (a typed full name, a consent checkbox).\n- The ink, placeholder and image are decorative (`aria-hidden`, empty `alt`).\n\n## Styling hooks\n\n- `data-slot`: `signature-frame`, `signature-pad`, `signature-ink`, `signature-image`, `signature-placeholder`, `signature-actions`.\n- On the pad: `data-filled=\"true\"` while it holds a signature, `data-drawing=\"true\"` during a stroke.\n\n## Theme parts\n\n`frame` (the pad and its buttons), `pad` (variants `size`, `interactive`, `disabled`, `hasError`), `ink` (the SVG of strokes), `image` (a value set from outside), `placeholder` (the signing line and hint), `actions` (the undo and clear buttons).\n\n## Exports\n\n`SignatureInput`, `SignatureInputProps`, `SignatureFormat`, `SignaturePoint`, `SignatureStroke`, `signatureInputTheme`, `setSignatureInputTheme`, `useSignatureInputTheme`, `SignatureInputTheme`, `SignatureInputThemeProps`.\n";
|
|
1
|
+
export declare const signatureInputDescription = "\n# SignatureInput Component\n\nSignatureInput is a form field where a person signs with a mouse, a finger or a pen. Its value is the signature as an image: a data URL cropped to the ink (PNG by default, or SVG), ready to store, submit or place in a document.\n\n## Basic usage\n\n```svelte\n<script lang=\"ts\">\n import { SignatureInput } from './index.ts';\n\n let signature = $state<string | null>(null);\n</script>\n\n<SignatureInput label=\"Signature\" required bind:value={signature} />\n```\n\nIn a Form or `ask()`, use `type: 'signature'`:\n\n```ts\nimport { ask } from 'entasis/ask';\n\nconst result = await ask({\n title: 'Sign the mandate',\n inputs: { signature: { type: 'signature', label: 'Signature', required: true } },\n confirm: 'Sign',\n cancel: 'Cancel'\n});\n```\n\n## Props\n\nExtends the shared Field props (`label`, `description`, `helper`, `required`, `disabled`, `readOnly`, `name`, `size`, `density`, `labelPosition`, `messages`, `onValidate`, `errors`, `focused`, `visible`) plus:\n\n- **value**: `string | null` (bindable) \u2014 the signature as a data URL, or `null` while the pad is empty.\n- **defaultValue**: `string | null` \u2014 initial value when `value` is omitted. Any image data URL works: a saved signature shows in the pad, scaled to fit.\n- **onValueChange**: `(value: string | null) => void` \u2014 called once per finished stroke, undo and clear.\n- **format**: `'png' | 'svg'` (default `'png'`) \u2014 the image the value holds. A PNG is drawn at twice the pad's resolution; an SVG keeps every stroke as a vector path.\n- **inkColor**: `string` (default `'#000000'`) \u2014 CSS color of the ink in the exported image, so a signature reads on a white document whatever the app's theme. The pad itself draws in the theme's text color.\n- **imageInk**: `'theme' | 'as-is'` (default `'theme'`) \u2014 how a value set from outside (a saved signature) shows in the pad. `'theme'` paints its shape in the pad's ink color, like live strokes (the image becomes a CSS mask over `bg-current`; only its transparency counts), so a black signature saved for paper reads on a dark theme without the app knowing which mode is on. `'as-is'` shows the image unchanged: for a signature with several colors or an opaque background. The value is never changed. A URL from another origin is fetched in CORS mode for the mask; when that origin refuses CORS, the pad falls back to the image as it is.\n- **strokeWidth**: `number` (default `2.5`) \u2014 line width in CSS pixels at a medium pen pressure. A pen's pressure makes the line thinner or thicker (half to one and a half times); a mouse or a finger draws at this width.\n- **placeholder**: `string` \u2014 hint on the signing line while the pad is empty. Defaults to the i18n `signatureInputPlaceholder` (\"Sign here\").\n- **clearLabel**, **undoLabel**: `string` \u2014 accessible labels and tooltips of the two buttons.\n- **i18n**: `Partial<Messages>` \u2014 per-instance translations.\n- **size**: `'small' | 'normal' | 'large'` \u2014 pad height (112, 144 or 176 px) and placeholder text size. Override the height with the `pad` theme part.\n- **theme**: `SignatureInputThemeProps` and Field theme parts.\n\n## Behaviour\n\n- Each stroke runs from pointer down to pointer up and is smoothed through its samples. The value updates when a stroke ends, not while it is drawn.\n- The undo button (or Ctrl/Cmd+Z on the pad) removes the last stroke; the clear button (or Delete/Backspace on the pad) empties the pad and sets the value to `null`. Both show only while the pad is editable and has a signature.\n- A value set from outside (a saved signature, a Form reset) replaces the strokes and shows as an image. Drawing over it starts a new signature: the image is replaced, not added to. Undo only steps back through strokes drawn since.\n- `disabled` and `readOnly` stop drawing and hide the buttons; a read-only pad still shows, focuses, validates and submits its value. A stroke in progress is dropped when the pad becomes disabled or read-only.\n- Required: an empty pad (`null` or `''`) fails `required`.\n- Native forms: a hidden input (`FieldHiddenInputs`) submits the data URL under `name`.\n\n## Accessibility\n\n- The pad is the field's control: it is focusable, labelled by the field label (or \"Signature\" without one), and has `role=\"img\"` with a description of its state (\"No signature yet\u2026\" or \"Signed.\"). Errors and descriptions are linked by Field.\n- Drawing is a path-based gesture with no keyboard equivalent: signing by hand is the purpose of the field. Keyboard users can clear and undo with the buttons and keys above. When a keyboard-only path to consent is needed, pair the pad with another field (a typed full name, a consent checkbox).\n- The ink, placeholder and image are decorative (`aria-hidden`, empty `alt`).\n\n## Styling hooks\n\n- `data-slot`: `signature-frame`, `signature-pad`, `signature-ink`, `signature-image`, `signature-placeholder`, `signature-actions`.\n- On the pad: `data-filled=\"true\"` while it holds a signature, `data-drawing=\"true\"` during a stroke.\n\n## Theme parts\n\n`frame` (the pad and its buttons), `pad` (variants `size`, `interactive`, `disabled`, `hasError`), `ink` (the SVG of strokes), `image` (a value set from outside), `placeholder` (the signing line and hint), `actions` (the undo and clear buttons).\n\n## Exports\n\n`SignatureInput`, `SignatureInputProps`, `SignatureFormat`, `SignaturePoint`, `SignatureStroke`, `signatureInputTheme`, `setSignatureInputTheme`, `useSignatureInputTheme`, `SignatureInputTheme`, `SignatureInputThemeProps`.\n";
|
|
@@ -37,6 +37,7 @@ Extends the shared Field props (\`label\`, \`description\`, \`helper\`, \`requir
|
|
|
37
37
|
- **onValueChange**: \`(value: string | null) => void\` — called once per finished stroke, undo and clear.
|
|
38
38
|
- **format**: \`'png' | 'svg'\` (default \`'png'\`) — the image the value holds. A PNG is drawn at twice the pad's resolution; an SVG keeps every stroke as a vector path.
|
|
39
39
|
- **inkColor**: \`string\` (default \`'#000000'\`) — CSS color of the ink in the exported image, so a signature reads on a white document whatever the app's theme. The pad itself draws in the theme's text color.
|
|
40
|
+
- **imageInk**: \`'theme' | 'as-is'\` (default \`'theme'\`) — how a value set from outside (a saved signature) shows in the pad. \`'theme'\` paints its shape in the pad's ink color, like live strokes (the image becomes a CSS mask over \`bg-current\`; only its transparency counts), so a black signature saved for paper reads on a dark theme without the app knowing which mode is on. \`'as-is'\` shows the image unchanged: for a signature with several colors or an opaque background. The value is never changed. A URL from another origin is fetched in CORS mode for the mask; when that origin refuses CORS, the pad falls back to the image as it is.
|
|
40
41
|
- **strokeWidth**: \`number\` (default \`2.5\`) — line width in CSS pixels at a medium pen pressure. A pen's pressure makes the line thinner or thicker (half to one and a half times); a mouse or a finger draws at this width.
|
|
41
42
|
- **placeholder**: \`string\` — hint on the signing line while the pad is empty. Defaults to the i18n \`signatureInputPlaceholder\` ("Sign here").
|
|
42
43
|
- **clearLabel**, **undoLabel**: \`string\` — accessible labels and tooltips of the two buttons.
|
|
@@ -3,6 +3,7 @@ import type { WithAttachments } from '../../../types/props.js';
|
|
|
3
3
|
import type { InputProps } from '../Field/field.js';
|
|
4
4
|
import type { SignatureFormat } from './signatureInput.strokes.js';
|
|
5
5
|
import type { SignatureInputThemeProps } from './signatureInput.theme.js';
|
|
6
|
+
export type SignatureImageInk = 'theme' | 'as-is';
|
|
6
7
|
export type SignatureInputProps = WithAttachments<Omit<InputProps<'signature'>, 'theme'> & {
|
|
7
8
|
/**
|
|
8
9
|
* Image the value holds, as a data URL cropped to the ink: `'png'` (default, drawn at twice
|
|
@@ -14,6 +15,14 @@ export type SignatureInputProps = WithAttachments<Omit<InputProps<'signature'>,
|
|
|
14
15
|
* white document whatever the app's theme; the pad itself draws in the theme's text color.
|
|
15
16
|
*/
|
|
16
17
|
inkColor?: string;
|
|
18
|
+
/**
|
|
19
|
+
* How a value set from outside (a saved signature) shows in the pad. `'theme'` (default)
|
|
20
|
+
* paints its shape in the pad's ink color, as live strokes are, so a black signature saved
|
|
21
|
+
* for paper still reads on a dark theme; only its transparency counts. `'as-is'` shows the
|
|
22
|
+
* image unchanged: for a signature with several colors or an opaque background. The value
|
|
23
|
+
* itself is never changed.
|
|
24
|
+
*/
|
|
25
|
+
imageInk?: SignatureImageInk;
|
|
17
26
|
/** Line width in CSS pixels at a medium pen pressure. Defaults to 2.5. */
|
|
18
27
|
strokeWidth?: number;
|
|
19
28
|
/** Hint on the signing line while the pad is empty. Defaults to the i18n `signatureInputPlaceholder`. */
|
|
@@ -21,7 +21,12 @@ export declare const signatureInputTheme: {
|
|
|
21
21
|
};
|
|
22
22
|
}> & import("../../../utils/cva/types.ts").CVAClassProp) | undefined) => string;
|
|
23
23
|
ink: (props?: import("../../../utils/cva/types.ts").CVAClassProp | undefined) => string;
|
|
24
|
-
image: (props?: import("../../../utils/cva/types.ts").
|
|
24
|
+
image: (props?: (import("../../../utils/cva/types.ts").CVAVariantSchema<{
|
|
25
|
+
ink: {
|
|
26
|
+
theme: string;
|
|
27
|
+
'as-is': string;
|
|
28
|
+
};
|
|
29
|
+
}> & import("../../../utils/cva/types.ts").CVAClassProp) | undefined) => string;
|
|
25
30
|
placeholder: (props?: (import("../../../utils/cva/types.ts").CVAVariantSchema<{
|
|
26
31
|
size: {
|
|
27
32
|
small: string;
|
|
@@ -55,7 +60,12 @@ export declare const setSignatureInputTheme: (theme: InferComponentTheme<{
|
|
|
55
60
|
};
|
|
56
61
|
}> & import("../../../utils/cva/types.ts").CVAClassProp) | undefined) => string;
|
|
57
62
|
ink: (props?: import("../../../utils/cva/types.ts").CVAClassProp | undefined) => string;
|
|
58
|
-
image: (props?: import("../../../utils/cva/types.ts").
|
|
63
|
+
image: (props?: (import("../../../utils/cva/types.ts").CVAVariantSchema<{
|
|
64
|
+
ink: {
|
|
65
|
+
theme: string;
|
|
66
|
+
'as-is': string;
|
|
67
|
+
};
|
|
68
|
+
}> & import("../../../utils/cva/types.ts").CVAClassProp) | undefined) => string;
|
|
59
69
|
placeholder: (props?: (import("../../../utils/cva/types.ts").CVAVariantSchema<{
|
|
60
70
|
size: {
|
|
61
71
|
small: string;
|
|
@@ -87,7 +97,12 @@ export declare const useSignatureInputTheme: import("../../../utils/cva/theme.ts
|
|
|
87
97
|
};
|
|
88
98
|
}> & import("../../../utils/cva/types.ts").CVAClassProp) | undefined) => string;
|
|
89
99
|
ink: (props?: import("../../../utils/cva/types.ts").CVAClassProp | undefined) => string;
|
|
90
|
-
image: (props?: import("../../../utils/cva/types.ts").
|
|
100
|
+
image: (props?: (import("../../../utils/cva/types.ts").CVAVariantSchema<{
|
|
101
|
+
ink: {
|
|
102
|
+
theme: string;
|
|
103
|
+
'as-is': string;
|
|
104
|
+
};
|
|
105
|
+
}> & import("../../../utils/cva/types.ts").CVAClassProp) | undefined) => string;
|
|
91
106
|
placeholder: (props?: (import("../../../utils/cva/types.ts").CVAVariantSchema<{
|
|
92
107
|
size: {
|
|
93
108
|
small: string;
|
|
@@ -37,9 +37,20 @@ const defaultPad = cva({
|
|
|
37
37
|
const defaultInk = cva({
|
|
38
38
|
base: 'pointer-events-none absolute inset-0 size-full overflow-visible'
|
|
39
39
|
});
|
|
40
|
-
// A value set from outside (a saved signature) shows
|
|
40
|
+
// A value set from outside (a saved signature) shows scaled to fit the pad. With `imageInk`
|
|
41
|
+
// 'theme' it is a mask over the pad's ink color (`bg-current`), so a black signature saved for
|
|
42
|
+
// paper reads on a dark surface; 'as-is' is the image itself.
|
|
41
43
|
const defaultImage = cva({
|
|
42
|
-
base: 'pointer-events-none absolute inset-0 size-full
|
|
44
|
+
base: 'pointer-events-none absolute inset-0 size-full p-md',
|
|
45
|
+
variants: {
|
|
46
|
+
ink: {
|
|
47
|
+
theme: 'bg-current [mask-clip:content-box] [mask-origin:content-box] [mask-position:center] [mask-repeat:no-repeat] [mask-size:contain]',
|
|
48
|
+
'as-is': 'object-contain'
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
defaultVariants: {
|
|
52
|
+
ink: 'theme'
|
|
53
|
+
}
|
|
43
54
|
});
|
|
44
55
|
// The line to sign on and its hint: decorative, gone as soon as there is ink.
|
|
45
56
|
const defaultPlaceholder = cva({
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
import SidebarFlyout from './SidebarFlyout.svelte';
|
|
29
29
|
import SidebarIcon from './SidebarIcon.svelte';
|
|
30
30
|
import SidebarMenuSubItem from './SidebarMenuSubItem.svelte';
|
|
31
|
+
import SidebarMenuText from './SidebarMenuText.svelte';
|
|
31
32
|
import { useSidebarSuffixWidth } from './sidebar.suffix.svelte.js';
|
|
32
33
|
import { useSidebarMotion, useSidebarTheme, type SidebarThemeProps } from './sidebar.theme.js';
|
|
33
34
|
|
|
@@ -82,6 +83,13 @@
|
|
|
82
83
|
);
|
|
83
84
|
const hasSubmenu = $derived(!!item.items?.length);
|
|
84
85
|
const showBadge = $derived(item.badge != null && !isIconCollapsed);
|
|
86
|
+
// A description stacks a second line under the label, so the row takes the large height
|
|
87
|
+
// unless the entry sets its own size.
|
|
88
|
+
const rowSize = $derived(item.size ?? (item.description != null ? 'large' : undefined));
|
|
89
|
+
const lead = $derived(item.media ? 'media' : 'icon');
|
|
90
|
+
// On a two-line row the suffix and the badge sit on the description's line, so the label's
|
|
91
|
+
// line, and its meta, run to the same end on every row.
|
|
92
|
+
const twoLine = $derived(item.description != null);
|
|
85
93
|
// An in-flow chevron or dots after the badge: the row then keeps its action's room at every
|
|
86
94
|
// width, since the action would otherwise cover that glyph when it shows.
|
|
87
95
|
const hasTrailingGlyph = $derived(
|
|
@@ -94,8 +102,12 @@
|
|
|
94
102
|
const endReserve = $derived(
|
|
95
103
|
item.suffix
|
|
96
104
|
? item.action
|
|
97
|
-
?
|
|
98
|
-
|
|
105
|
+
? twoLine
|
|
106
|
+
? 'suffixLineAction'
|
|
107
|
+
: 'suffixAction'
|
|
108
|
+
: twoLine
|
|
109
|
+
? 'suffixLine'
|
|
110
|
+
: 'suffix'
|
|
99
111
|
: !item.action
|
|
100
112
|
? 'none'
|
|
101
113
|
: showBadge && !hasTrailingGlyph
|
|
@@ -176,7 +188,11 @@
|
|
|
176
188
|
</script>
|
|
177
189
|
|
|
178
190
|
{#snippet entryContent()}
|
|
179
|
-
{#if
|
|
191
|
+
{#if item.media}
|
|
192
|
+
<span data-slot="sidebar-menu-media" data-sidebar="menu-media" class={classes.menuMedia()}>
|
|
193
|
+
{@render item.media(api, item)}
|
|
194
|
+
</span>
|
|
195
|
+
{:else if hasIconSurface}
|
|
180
196
|
<span
|
|
181
197
|
data-slot="sidebar-menu-icon"
|
|
182
198
|
data-color={item.iconColor}
|
|
@@ -187,7 +203,25 @@
|
|
|
187
203
|
{:else}
|
|
188
204
|
<SidebarIcon icon={item.icon} class={back ? 'rtl:-scale-x-100' : undefined} />
|
|
189
205
|
{/if}
|
|
190
|
-
|
|
206
|
+
{#if item.description != null || item.meta != null}
|
|
207
|
+
<SidebarMenuText
|
|
208
|
+
label={item.label}
|
|
209
|
+
description={item.description}
|
|
210
|
+
meta={isIconCollapsed ? undefined : item.meta}
|
|
211
|
+
suffix={!!item.suffix}
|
|
212
|
+
trailing={twoLine ? badge : undefined}
|
|
213
|
+
{size}
|
|
214
|
+
{theme}
|
|
215
|
+
/>
|
|
216
|
+
{:else}
|
|
217
|
+
<span class={classes.menuLabel()}>{item.label}</span>
|
|
218
|
+
{/if}
|
|
219
|
+
{#if !twoLine}
|
|
220
|
+
{@render badge()}
|
|
221
|
+
{/if}
|
|
222
|
+
{/snippet}
|
|
223
|
+
|
|
224
|
+
{#snippet badge()}
|
|
191
225
|
{#if showBadge}
|
|
192
226
|
<span
|
|
193
227
|
data-slot="sidebar-menu-badge"
|
|
@@ -224,7 +258,7 @@
|
|
|
224
258
|
role={item.disabled ? 'link' : undefined}
|
|
225
259
|
data-slot="sidebar-menu-button"
|
|
226
260
|
data-sidebar="menu-button"
|
|
227
|
-
data-size={
|
|
261
|
+
data-size={rowSize ?? 'normal'}
|
|
228
262
|
data-active={item.isActive ? 'true' : undefined}
|
|
229
263
|
data-active-variant={activeVariant}
|
|
230
264
|
aria-current={item.isActive ? 'page' : undefined}
|
|
@@ -236,7 +270,8 @@
|
|
|
236
270
|
activeVariant,
|
|
237
271
|
size,
|
|
238
272
|
density,
|
|
239
|
-
itemSize:
|
|
273
|
+
itemSize: rowSize,
|
|
274
|
+
lead,
|
|
240
275
|
endReserve,
|
|
241
276
|
className: item.class
|
|
242
277
|
})}
|
|
@@ -254,7 +289,7 @@
|
|
|
254
289
|
type="button"
|
|
255
290
|
data-slot="sidebar-menu-button"
|
|
256
291
|
data-sidebar="menu-button"
|
|
257
|
-
data-size={
|
|
292
|
+
data-size={rowSize ?? 'normal'}
|
|
258
293
|
data-active={item.isActive ? 'true' : undefined}
|
|
259
294
|
data-active-variant={activeVariant}
|
|
260
295
|
aria-current={item.isActive ? 'page' : undefined}
|
|
@@ -267,7 +302,8 @@
|
|
|
267
302
|
activeVariant,
|
|
268
303
|
size,
|
|
269
304
|
density,
|
|
270
|
-
itemSize:
|
|
305
|
+
itemSize: rowSize,
|
|
306
|
+
lead,
|
|
271
307
|
endReserve,
|
|
272
308
|
className: item.class
|
|
273
309
|
})}
|
|
@@ -302,7 +338,7 @@
|
|
|
302
338
|
type="button"
|
|
303
339
|
data-slot="sidebar-menu-button"
|
|
304
340
|
data-sidebar="menu-button"
|
|
305
|
-
data-size={
|
|
341
|
+
data-size={rowSize ?? 'normal'}
|
|
306
342
|
data-active-variant={activeVariant}
|
|
307
343
|
disabled={item.disabled || undefined}
|
|
308
344
|
class={classes.menuButton({
|
|
@@ -310,7 +346,8 @@
|
|
|
310
346
|
activeVariant,
|
|
311
347
|
size,
|
|
312
348
|
density,
|
|
313
|
-
itemSize:
|
|
349
|
+
itemSize: rowSize,
|
|
350
|
+
lead,
|
|
314
351
|
endReserve,
|
|
315
352
|
className: ['aria-expanded:bg-neutral-muted', item.class]
|
|
316
353
|
})}
|
|
@@ -339,7 +376,7 @@
|
|
|
339
376
|
type="button"
|
|
340
377
|
data-slot="sidebar-menu-button"
|
|
341
378
|
data-sidebar="menu-button"
|
|
342
|
-
data-size={
|
|
379
|
+
data-size={rowSize ?? 'normal'}
|
|
343
380
|
data-active={item.isActive ? 'true' : undefined}
|
|
344
381
|
data-active-variant={activeVariant}
|
|
345
382
|
class={classes.menuButton({
|
|
@@ -347,7 +384,8 @@
|
|
|
347
384
|
activeVariant,
|
|
348
385
|
size,
|
|
349
386
|
density,
|
|
350
|
-
itemSize:
|
|
387
|
+
itemSize: rowSize,
|
|
388
|
+
lead,
|
|
351
389
|
endReserve,
|
|
352
390
|
className: item.class
|
|
353
391
|
})}
|
|
@@ -434,7 +472,7 @@
|
|
|
434
472
|
type="button"
|
|
435
473
|
data-slot="sidebar-menu-button"
|
|
436
474
|
data-sidebar="menu-button"
|
|
437
|
-
data-size={
|
|
475
|
+
data-size={rowSize ?? 'normal'}
|
|
438
476
|
data-active={item.isActive ? 'true' : undefined}
|
|
439
477
|
data-active-variant={activeVariant}
|
|
440
478
|
disabled={item.disabled || undefined}
|
|
@@ -443,7 +481,8 @@
|
|
|
443
481
|
activeVariant,
|
|
444
482
|
size,
|
|
445
483
|
density,
|
|
446
|
-
itemSize:
|
|
484
|
+
itemSize: rowSize,
|
|
485
|
+
lead,
|
|
447
486
|
endReserve,
|
|
448
487
|
className: item.class
|
|
449
488
|
})}
|
|
@@ -473,7 +512,12 @@
|
|
|
473
512
|
data-sidebar="menu-suffix"
|
|
474
513
|
inert={isIconCollapsed ? true : undefined}
|
|
475
514
|
aria-hidden={isIconCollapsed ? 'true' : undefined}
|
|
476
|
-
class={classes.suffix({
|
|
515
|
+
class={classes.suffix({
|
|
516
|
+
size,
|
|
517
|
+
density,
|
|
518
|
+
action: item.action ? 'action' : 'none',
|
|
519
|
+
line: twoLine ? 'two' : 'one'
|
|
520
|
+
})}
|
|
477
521
|
{@attach suffixWidth.measure}
|
|
478
522
|
>
|
|
479
523
|
{@render item.suffix(api, item)}
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
import { sidebarInwardPhysicalSide, sidebarTooltip } from './sidebar-position.js';
|
|
12
12
|
import SidebarAction from './SidebarAction.svelte';
|
|
13
13
|
import SidebarIcon from './SidebarIcon.svelte';
|
|
14
|
+
import SidebarMenuText from './SidebarMenuText.svelte';
|
|
14
15
|
import { useSidebarSuffixWidth } from './sidebar.suffix.svelte.js';
|
|
15
16
|
import { useSidebarTheme, type SidebarThemeProps } from './sidebar.theme.js';
|
|
16
17
|
|
|
@@ -39,6 +40,9 @@
|
|
|
39
40
|
// tile, so an untinted row never inherits the ambient `data-color`.
|
|
40
41
|
const hasIconSurface = $derived(!!sub.icon && (sub.iconVariant === 'tile' || !!sub.iconColor));
|
|
41
42
|
const hasBadge = $derived(sub.badge != null);
|
|
43
|
+
// On a two-line row the suffix and the badge sit on the description's line, so the label's
|
|
44
|
+
// line, and its meta, run to the same end on every row.
|
|
45
|
+
const twoLine = $derived(sub.description != null);
|
|
42
46
|
const suffixWidth = useSidebarSuffixWidth();
|
|
43
47
|
const uid = $props.id();
|
|
44
48
|
const suffixId = `${uid}-suffix`;
|
|
@@ -63,13 +67,18 @@
|
|
|
63
67
|
// stays visible before the action, so a row with one reserves both at every width.
|
|
64
68
|
endReserve: sub.suffix
|
|
65
69
|
? sub.action
|
|
66
|
-
?
|
|
67
|
-
|
|
70
|
+
? twoLine
|
|
71
|
+
? 'suffixLineAction'
|
|
72
|
+
: 'suffixAction'
|
|
73
|
+
: twoLine
|
|
74
|
+
? 'suffixLine'
|
|
75
|
+
: 'suffix'
|
|
68
76
|
: !sub.action
|
|
69
77
|
? 'none'
|
|
70
78
|
: hasBadge
|
|
71
79
|
? 'actionBelowMd'
|
|
72
80
|
: 'action',
|
|
81
|
+
tall: sub.description != null || sub.media != null,
|
|
73
82
|
className: sub.class
|
|
74
83
|
})
|
|
75
84
|
);
|
|
@@ -85,7 +94,11 @@
|
|
|
85
94
|
</script>
|
|
86
95
|
|
|
87
96
|
{#snippet entryContent()}
|
|
88
|
-
{#if
|
|
97
|
+
{#if sub.media}
|
|
98
|
+
<span data-slot="sidebar-menu-media" data-sidebar="menu-media" class={classes.menuMedia()}>
|
|
99
|
+
{@render sub.media(api, sub)}
|
|
100
|
+
</span>
|
|
101
|
+
{:else if hasIconSurface}
|
|
89
102
|
<span
|
|
90
103
|
data-slot="sidebar-menu-icon"
|
|
91
104
|
data-color={sub.iconColor}
|
|
@@ -100,20 +113,37 @@
|
|
|
100
113
|
{:else}
|
|
101
114
|
<SidebarIcon icon={sub.icon} />
|
|
102
115
|
{/if}
|
|
103
|
-
{#if
|
|
116
|
+
{#if sub.description != null || sub.meta != null}
|
|
117
|
+
<SidebarMenuText
|
|
118
|
+
label={sub.label}
|
|
119
|
+
description={sub.description}
|
|
120
|
+
meta={sub.meta}
|
|
121
|
+
suffix={!!sub.suffix}
|
|
122
|
+
trailing={twoLine && hasBadge ? badge : undefined}
|
|
123
|
+
size={subSize}
|
|
124
|
+
{theme}
|
|
125
|
+
/>
|
|
126
|
+
{#if !twoLine && hasBadge}
|
|
127
|
+
{@render badge()}
|
|
128
|
+
{/if}
|
|
129
|
+
{:else if hasBadge}
|
|
104
130
|
<span data-slot="sidebar-menu-sub-label">{sub.label}</span>
|
|
105
|
-
|
|
106
|
-
data-slot="sidebar-menu-sub-badge"
|
|
107
|
-
data-sidebar="menu-sub-badge"
|
|
108
|
-
class={classes.badge({ size: subSize, action: sub.action && !sub.suffix ? 'sub' : 'none' })}
|
|
109
|
-
>
|
|
110
|
-
{sub.badge}
|
|
111
|
-
</span>
|
|
131
|
+
{@render badge()}
|
|
112
132
|
{:else}
|
|
113
133
|
<span>{sub.label}</span>
|
|
114
134
|
{/if}
|
|
115
135
|
{/snippet}
|
|
116
136
|
|
|
137
|
+
{#snippet badge()}
|
|
138
|
+
<span
|
|
139
|
+
data-slot="sidebar-menu-sub-badge"
|
|
140
|
+
data-sidebar="menu-sub-badge"
|
|
141
|
+
class={classes.badge({ size: subSize, action: sub.action && !sub.suffix ? 'sub' : 'none' })}
|
|
142
|
+
>
|
|
143
|
+
{sub.badge}
|
|
144
|
+
</span>
|
|
145
|
+
{/snippet}
|
|
146
|
+
|
|
117
147
|
<li
|
|
118
148
|
bind:this={itemRef}
|
|
119
149
|
data-slot="sidebar-menu-sub-item"
|
|
@@ -175,7 +205,8 @@
|
|
|
175
205
|
class={classes.suffix({
|
|
176
206
|
size: subSize,
|
|
177
207
|
density,
|
|
178
|
-
action: sub.action ? 'action' : 'none'
|
|
208
|
+
action: sub.action ? 'action' : 'none',
|
|
209
|
+
line: twoLine ? 'two' : 'one'
|
|
179
210
|
})}
|
|
180
211
|
{@attach suffixWidth.measure}
|
|
181
212
|
>
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import type { SidebarSize } from './sidebar.props.js';
|
|
4
|
+
import { useSidebarTheme, type SidebarThemeProps } from './sidebar.theme.js';
|
|
5
|
+
|
|
6
|
+
let {
|
|
7
|
+
label,
|
|
8
|
+
description,
|
|
9
|
+
meta,
|
|
10
|
+
size,
|
|
11
|
+
suffix = false,
|
|
12
|
+
trailing,
|
|
13
|
+
theme
|
|
14
|
+
}: {
|
|
15
|
+
label: string;
|
|
16
|
+
description?: string | Snippet;
|
|
17
|
+
/** Left out while the Sidebar is collapsed to icons. */
|
|
18
|
+
meta?: string | Snippet;
|
|
19
|
+
size: SidebarSize;
|
|
20
|
+
/** The row has a suffix, centred on the description's line. */
|
|
21
|
+
suffix?: boolean;
|
|
22
|
+
/** End of the description's line: the row's badge. */
|
|
23
|
+
trailing?: Snippet;
|
|
24
|
+
theme?: SidebarThemeProps;
|
|
25
|
+
} = $props();
|
|
26
|
+
|
|
27
|
+
const classes = $derived(useSidebarTheme(theme));
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
{#snippet text(content: string | Snippet)}
|
|
31
|
+
{#if typeof content === 'string'}{content}{:else}{@render content()}{/if}
|
|
32
|
+
{/snippet}
|
|
33
|
+
|
|
34
|
+
<!-- The label's line (the label, then the meta at its end) over the description's line. -->
|
|
35
|
+
<span data-slot="sidebar-menu-text" class={classes.menuText()}>
|
|
36
|
+
<span class={classes.menuTitleRow()}>
|
|
37
|
+
<span data-slot="sidebar-menu-label" class={classes.menuTitle()}>{label}</span>
|
|
38
|
+
{#if meta != null}
|
|
39
|
+
<span
|
|
40
|
+
data-slot="sidebar-menu-meta"
|
|
41
|
+
data-sidebar="menu-meta"
|
|
42
|
+
class={classes.menuMeta({ size })}
|
|
43
|
+
>
|
|
44
|
+
{@render text(meta)}
|
|
45
|
+
</span>
|
|
46
|
+
{/if}
|
|
47
|
+
</span>
|
|
48
|
+
{#if description != null}
|
|
49
|
+
<span class={classes.menuDescriptionRow({ suffix })}>
|
|
50
|
+
<span
|
|
51
|
+
data-slot="sidebar-menu-description"
|
|
52
|
+
data-sidebar="menu-description"
|
|
53
|
+
class={classes.menuSecondary({ size })}
|
|
54
|
+
>
|
|
55
|
+
{@render text(description)}
|
|
56
|
+
</span>
|
|
57
|
+
{@render trailing?.()}
|
|
58
|
+
</span>
|
|
59
|
+
{/if}
|
|
60
|
+
</span>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { SidebarSize } from './sidebar.props.js';
|
|
3
|
+
import { type SidebarThemeProps } from './sidebar.theme.js';
|
|
4
|
+
type $$ComponentProps = {
|
|
5
|
+
label: string;
|
|
6
|
+
description?: string | Snippet;
|
|
7
|
+
/** Left out while the Sidebar is collapsed to icons. */
|
|
8
|
+
meta?: string | Snippet;
|
|
9
|
+
size: SidebarSize;
|
|
10
|
+
/** The row has a suffix, centred on the description's line. */
|
|
11
|
+
suffix?: boolean;
|
|
12
|
+
/** End of the description's line: the row's badge. */
|
|
13
|
+
trailing?: Snippet;
|
|
14
|
+
theme?: SidebarThemeProps;
|
|
15
|
+
};
|
|
16
|
+
declare const SidebarMenuText: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
17
|
+
type SidebarMenuText = ReturnType<typeof SidebarMenuText>;
|
|
18
|
+
export default SidebarMenuText;
|