@k2b/ui 0.48.0 → 0.49.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.
Files changed (46) hide show
  1. package/dist/browser/actions/CopyButton.js +26 -18
  2. package/dist/browser/actions/CopyButton.js.map +1 -1
  3. package/dist/browser/feedback/prompt-confirm.js +7 -4
  4. package/dist/browser/feedback/prompt-confirm.js.map +1 -1
  5. package/dist/browser/feedback/prompts.js +3 -3
  6. package/dist/browser/feedback/prompts.js.map +1 -1
  7. package/dist/browser/inputs/NumberInput.js +17 -5
  8. package/dist/browser/inputs/NumberInput.js.map +1 -1
  9. package/dist/browser/layout/AppWorkspace.js +574 -522
  10. package/dist/browser/layout/AppWorkspace.js.map +1 -1
  11. package/dist/browser/layout/MobileShell.js +26 -0
  12. package/dist/browser/layout/MobileShell.js.map +1 -1
  13. package/dist/browser/layout/index.js +1 -0
  14. package/dist/browser/layout/index.js.map +1 -1
  15. package/dist/browser/layout/sheet-handle.js +155 -0
  16. package/dist/browser/layout/sheet-handle.js.map +1 -0
  17. package/dist/browser/surfaces/NoticeCard.js +48 -29
  18. package/dist/browser/surfaces/NoticeCard.js.map +1 -1
  19. package/dist/ssr/actions/CopyButton.js +13 -8
  20. package/dist/ssr/actions/CopyButton.js.map +1 -1
  21. package/dist/ssr/feedback/prompt-confirm.js +7 -4
  22. package/dist/ssr/feedback/prompt-confirm.js.map +1 -1
  23. package/dist/ssr/feedback/prompts.js +3 -3
  24. package/dist/ssr/feedback/prompts.js.map +1 -1
  25. package/dist/ssr/inputs/NumberInput.js +17 -5
  26. package/dist/ssr/inputs/NumberInput.js.map +1 -1
  27. package/dist/ssr/layout/AppWorkspace.js +152 -114
  28. package/dist/ssr/layout/AppWorkspace.js.map +1 -1
  29. package/dist/ssr/layout/MobileShell.js +26 -0
  30. package/dist/ssr/layout/MobileShell.js.map +1 -1
  31. package/dist/ssr/layout/index.js +1 -0
  32. package/dist/ssr/layout/index.js.map +1 -1
  33. package/dist/ssr/layout/sheet-handle.js +155 -0
  34. package/dist/ssr/layout/sheet-handle.js.map +1 -0
  35. package/dist/ssr/surfaces/NoticeCard.js +25 -10
  36. package/dist/ssr/surfaces/NoticeCard.js.map +1 -1
  37. package/dist/styles.css +1 -1
  38. package/dist/types/feedback/prompt-confirm.d.ts +3 -1
  39. package/dist/types/feedback/prompts.d.ts +2 -2
  40. package/dist/types/inputs/NumberInput.d.ts +1 -1
  41. package/dist/types/layout/AppWorkspace.d.ts +16 -1
  42. package/dist/types/layout/MobileShell.d.ts +5 -0
  43. package/dist/types/layout/index.d.ts +2 -1
  44. package/dist/types/layout/sheet-handle.d.ts +21 -0
  45. package/dist/types/surfaces/NoticeCard.d.ts +5 -2
  46. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["surfaces/NoticeCard.tsx"],"sourcesContent":["import { children, For, type JSX, Show, splitProps } from \"solid-js\";\nimport type { IntentTone } from \"../semantics\";\n\nexport type NoticeTone = Extract<IntentTone, \"neutral\" | \"info\" | \"success\" | \"warning\" | \"danger\">;\n\ntype NoticeCardContentProps =\n | { title: JSX.Element; detail?: JSX.Element; meta?: JSX.Element; children?: JSX.Element }\n | { title?: never; detail?: never; meta?: never; children: JSX.Element };\n\nexport type NoticeCardProps = Omit<JSX.HTMLAttributes<HTMLElement>, \"children\" | \"class\" | \"title\"> &\n NoticeCardContentProps & {\n tone?: NoticeTone;\n /** A Tabler icon class. Turns the notice into a compact status line whose icon and text take the tone colour. */\n icon?: string;\n class?: string;\n bodyClass?: string;\n };\n\nexport const NOTICE_CARD_CLASSES = {\n root: \"k2b-notice-card\",\n icon: \"k2b-notice-card__icon\",\n content: \"k2b-notice-card__content\",\n head: \"k2b-notice-card__head\",\n title: \"k2b-notice-card__title\",\n meta: \"k2b-notice-card__meta\",\n description: \"k2b-notice-card__description\",\n body: \"k2b-notice-card__body\",\n} as const;\n\nfunction NoticeCardComponent(props: NoticeCardProps): JSX.Element {\n const [local, articleProps] = splitProps(props, [\"tone\", \"icon\", \"title\", \"detail\", \"meta\", \"children\", \"class\", \"bodyClass\"]);\n // Children that render nothing, such as a Show whose condition is false, add no body and no gap.\n const body = children(() => local.children);\n const hasBody = () => body.toArray().some((node) => node != null && node !== false && node !== \"\");\n return (\n <article\n {...articleProps}\n class={`${NOTICE_CARD_CLASSES.root} ${local.class ?? \"\"}`}\n data-tone={local.tone ?? \"neutral\"}\n {...(local.icon ? { \"data-icon\": \"\" } : {})}\n >\n <Show when={local.icon}>{(icon) => <i class={`${icon()} ${NOTICE_CARD_CLASSES.icon}`} aria-hidden=\"true\" />}</Show>\n <div class={NOTICE_CARD_CLASSES.content}>\n <Show when={local.title}>\n {(title) => (\n <div class={NOTICE_CARD_CLASSES.head}>\n <p class={NOTICE_CARD_CLASSES.title}>{title()}</p>\n <Show when={local.meta}>{(meta) => <span class={NOTICE_CARD_CLASSES.meta}>{meta()}</span>}</Show>\n </div>\n )}\n </Show>\n <Show when={local.detail}>{(detail) => <p class={NOTICE_CARD_CLASSES.description}>{detail()}</p>}</Show>\n <Show when={hasBody()}>\n <div class={`${NOTICE_CARD_CLASSES.body} ${local.bodyClass ?? \"\"}`}>{body()}</div>\n </Show>\n </div>\n </article>\n );\n}\n\nexport type NoticeGridProps<T> = {\n items: readonly T[];\n children: (item: T) => JSX.Element;\n class?: string;\n};\n\nfunction NoticeGrid<T>(props: NoticeGridProps<T>): JSX.Element {\n const columns = () => (props.items.length <= 1 ? \"one\" : props.items.length === 2 ? \"two\" : \"three\");\n return (\n <Show when={props.items.length > 0}>\n <div class={`k2b-notice-grid ${props.class ?? \"\"}`} data-columns={columns()}>\n <For each={props.items}>{(item) => props.children(item)}</For>\n </div>\n </Show>\n );\n}\n\nexport const NoticeCard = Object.assign(NoticeCardComponent, { Grid: NoticeGrid });\nexport default NoticeCard;\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":[],"sources":["surfaces/NoticeCard.tsx"],"sourcesContent":["import { children, For, type JSX, Show, splitProps } from \"solid-js\";\nimport { dialogToneIcon, dialogToneLabel } from \"../feedback/dialog-tone\";\nimport { useUiMessages } from \"../intl/messages\";\nimport type { IntentTone } from \"../semantics\";\n\nexport type NoticeTone = Extract<IntentTone, \"neutral\" | \"info\" | \"success\" | \"warning\" | \"danger\">;\n\ntype NoticeCardContentProps =\n | { title: JSX.Element; detail?: JSX.Element; meta?: JSX.Element; children?: JSX.Element }\n | { title?: never; detail?: never; meta?: never; children: JSX.Element };\n\nexport type NoticeCardProps = Omit<JSX.HTMLAttributes<HTMLElement>, \"children\" | \"class\" | \"title\"> &\n NoticeCardContentProps & {\n tone?: NoticeTone;\n /**\n * A Tabler icon class. Turns the notice into a compact status line whose icon and text take the tone colour. `true`\n * takes the tone's own icon, the one a toned dialog shows, and names the tone for screen readers.\n */\n icon?: string | true;\n class?: string;\n bodyClass?: string;\n };\n\nexport const NOTICE_CARD_CLASSES = {\n root: \"k2b-notice-card\",\n icon: \"k2b-notice-card__icon\",\n content: \"k2b-notice-card__content\",\n head: \"k2b-notice-card__head\",\n title: \"k2b-notice-card__title\",\n meta: \"k2b-notice-card__meta\",\n description: \"k2b-notice-card__description\",\n body: \"k2b-notice-card__body\",\n} as const;\n\nfunction NoticeCardComponent(props: NoticeCardProps): JSX.Element {\n const [local, articleProps] = splitProps(props, [\"tone\", \"icon\", \"title\", \"detail\", \"meta\", \"children\", \"class\", \"bodyClass\"]);\n // Children that render nothing, such as a Show whose condition is false, add no body and no gap.\n const body = children(() => local.children);\n const hasBody = () => body.toArray().some((node) => node != null && node !== false && node !== \"\");\n const messages = useUiMessages();\n /** The tone a dialog also knows, so `icon` true shows the same icon and word; info and neutral have no word. */\n const dialogTone = () => (local.tone === \"success\" || local.tone === \"warning\" || local.tone === \"danger\" ? local.tone : undefined);\n const icon = () => {\n if (local.icon !== true) return local.icon;\n const tone = dialogTone();\n return tone ? dialogToneIcon(tone) : \"ti ti-info-circle\";\n };\n const toneWord = () => {\n const tone = local.icon === true ? dialogTone() : undefined;\n return tone ? `${dialogToneLabel(messages(), tone)}: ` : undefined;\n };\n return (\n <article\n {...articleProps}\n class={`${NOTICE_CARD_CLASSES.root} ${local.class ?? \"\"}`}\n data-tone={local.tone ?? \"neutral\"}\n {...(local.icon ? { \"data-icon\": \"\" } : {})}\n >\n <Show when={icon()}>\n {(icon) => (\n <>\n <i class={`${icon()} ${NOTICE_CARD_CLASSES.icon}`} aria-hidden=\"true\" />\n {/* Inside the icon's branch, so a notice without one keeps its markup. */}\n {toneWord() ? <span class=\"k2b-sr-only\">{toneWord()}</span> : null}\n </>\n )}\n </Show>\n <div class={NOTICE_CARD_CLASSES.content}>\n <Show when={local.title}>\n {(title) => (\n <div class={NOTICE_CARD_CLASSES.head}>\n <p class={NOTICE_CARD_CLASSES.title}>{title()}</p>\n <Show when={local.meta}>{(meta) => <span class={NOTICE_CARD_CLASSES.meta}>{meta()}</span>}</Show>\n </div>\n )}\n </Show>\n <Show when={local.detail}>{(detail) => <p class={NOTICE_CARD_CLASSES.description}>{detail()}</p>}</Show>\n <Show when={hasBody()}>\n <div class={`${NOTICE_CARD_CLASSES.body} ${local.bodyClass ?? \"\"}`}>{body()}</div>\n </Show>\n </div>\n </article>\n );\n}\n\nexport type NoticeGridProps<T> = {\n items: readonly T[];\n children: (item: T) => JSX.Element;\n class?: string;\n};\n\nfunction NoticeGrid<T>(props: NoticeGridProps<T>): JSX.Element {\n const columns = () => (props.items.length <= 1 ? \"one\" : props.items.length === 2 ? \"two\" : \"three\");\n return (\n <Show when={props.items.length > 0}>\n <div class={`k2b-notice-grid ${props.class ?? \"\"}`} data-columns={columns()}>\n <For each={props.items}>{(item) => props.children(item)}</For>\n </div>\n </Show>\n );\n}\n\nexport const NoticeCard = Object.assign(NoticeCardComponent, { Grid: NoticeGrid });\nexport default NoticeCard;\n"],"mappings":"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","ignoreList":[]}
@@ -1,12 +1,12 @@
1
1
  import { createComponent as _$createComponent } from "solid-js/web";
2
2
  import { mergeProps as _$mergeProps } from "solid-js/web";
3
- import { ssr as _$ssr } from "solid-js/web";
4
3
  import { ssrAttribute as _$ssrAttribute } from "solid-js/web";
5
- import { escape as _$escape } from "solid-js/web";
6
4
  import { memo as _$memo } from "solid-js/web";
7
- var _tmpl$ = ["<i", " aria-hidden=\"true\"></i>"],
8
- _tmpl$2 = ["<span>", "</span>"],
9
- _tmpl$3 = ["<span class=\"k2b-sr-only\" aria-live=\"polite\">", "</span>"];
5
+ import { ssr as _$ssr } from "solid-js/web";
6
+ import { escape as _$escape } from "solid-js/web";
7
+ var _tmpl$ = ["<span class=\"k2b-sr-only\" aria-live=\"polite\">", "</span>"],
8
+ _tmpl$2 = ["<i", " aria-hidden=\"true\"></i>"],
9
+ _tmpl$3 = ["<span class=\"k2b-copy-button__label\"", "><span>", "</span></span>"];
10
10
  import { copyToClipboard } from "@k2b/stdlib/browser";
11
11
  import { createSignal, onCleanup, splitProps } from "solid-js";
12
12
  import { useUiMessages } from "../intl/messages";
@@ -42,9 +42,14 @@ export function CopyButton(props) {
42
42
  if (resetTimer) clearTimeout(resetTimer);
43
43
  resetTimer = setTimeout(() => setCopied(false), local.resetAfter ?? 2000);
44
44
  };
45
- const visibleLabel = () => copied() ? local.copiedLabel ?? messages().copied : local.label ?? messages().copy;
45
+ const copyLabel = () => local.label ?? messages().copy;
46
+ const copiedLabel = () => local.copiedLabel ?? messages().copied;
47
+ const visibleLabel = () => copied() ? copiedLabel() : copyLabel();
46
48
  const icon = () => copied() ? "ti ti-check" : "ti ti-copy";
47
49
  const iconOnly = () => local.iconOnly ?? local.label === undefined;
50
+ // Copied often flashes into a row next to a field; the other label, drawn hidden by CSS, keeps the button's width.
51
+ const hiddenLabel = () => copied() ? copyLabel() : copiedLabel();
52
+ const announcement = () => _$ssr(_tmpl$, copied() ? _$escape(visibleLabel()) : "");
48
53
  const button = tooltip => _$createComponent(Button, _$mergeProps(rest, {
49
54
  tooltip: tooltip,
50
55
  get disabled() {
@@ -73,10 +78,10 @@ export function CopyButton(props) {
73
78
  },
74
79
  onClick: copy,
75
80
  get children() {
76
- return [_$ssr(_tmpl$, _$ssrAttribute("class", _$escape(icon(), true), false)), !iconOnly() && _$ssr(_tmpl$2, _$escape(visibleLabel()))];
81
+ return [_$ssr(_tmpl$2, _$ssrAttribute("class", _$escape(icon(), true), false)), !iconOnly() && _$ssr(_tmpl$3, _$ssrAttribute("data-reserve", _$escape(hiddenLabel(), true), false), _$escape(visibleLabel()))];
77
82
  }
78
83
  }));
79
- return iconOnly() ? [button(visibleLabel()), _$ssr(_tmpl$3, copied() ? _$escape(visibleLabel()) : "")] : button(undefined);
84
+ return [button(iconOnly() ? visibleLabel() : undefined), announcement()];
80
85
  }
81
86
  export default CopyButton;
82
87
  //# sourceMappingURL=CopyButton.js.map
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["actions/CopyButton.tsx"],"sourcesContent":["import { copyToClipboard } from \"@k2b/stdlib/browser\";\nimport { createSignal, type JSX, onCleanup, splitProps } from \"solid-js\";\nimport { useUiMessages } from \"../intl/messages\";\nimport { Button, type ButtonProps } from \"./Button\";\n\nexport type CopyButtonValue = { text: string; value?: string } | { text?: string; value: string };\n\nexport type CopyButtonProps = CopyButtonValue &\n Omit<ButtonProps, \"children\" | \"onClick\"> & {\n label?: string;\n copiedLabel?: string;\n iconOnly?: boolean;\n onCopied?: () => void;\n onCopyError?: (error: unknown) => void;\n resetAfter?: number;\n };\n\nexport async function copyText(\n text: string,\n onCopyError?: (error: unknown) => void,\n copy: (text: string) => Promise<void> = copyToClipboard,\n): Promise<void> {\n try {\n await copy(text);\n } catch (error) {\n onCopyError?.(error);\n throw error;\n }\n}\n\nexport function CopyButton(props: CopyButtonProps): JSX.Element {\n const messages = useUiMessages();\n const [local, rest] = splitProps(props, [\n \"class\",\n \"copiedLabel\",\n \"disabled\",\n \"iconOnly\",\n \"label\",\n \"loading\",\n \"loadingLabel\",\n \"onCopied\",\n \"onCopyError\",\n \"resetAfter\",\n \"size\",\n \"text\",\n \"type\",\n \"value\",\n \"variant\",\n ]);\n const [copied, setCopied] = createSignal(false);\n let resetTimer: ReturnType<typeof setTimeout> | undefined;\n\n onCleanup(() => {\n if (resetTimer) clearTimeout(resetTimer);\n });\n\n const copy = async () => {\n // `copyText` reports through `onCopyError` and then rethrows so direct\n // callers can await it. The click handler is not awaited by anyone, so it\n // has to absorb the rejection here — otherwise a denied clipboard\n // permission surfaces as an unhandled rejection despite `onCopyError`.\n try {\n await copyText(local.text ?? local.value ?? \"\", local.onCopyError);\n } catch {\n return;\n }\n setCopied(true);\n local.onCopied?.();\n if (resetTimer) clearTimeout(resetTimer);\n resetTimer = setTimeout(() => setCopied(false), local.resetAfter ?? 2000);\n };\n\n const visibleLabel = () => (copied() ? (local.copiedLabel ?? messages().copied) : (local.label ?? messages().copy));\n const icon = () => (copied() ? \"ti ti-check\" : \"ti ti-copy\");\n const iconOnly = () => local.iconOnly ?? local.label === undefined;\n const button = (tooltip?: string) => (\n <Button\n {...rest}\n tooltip={tooltip}\n disabled={local.disabled}\n loading={local.loading}\n loadingLabel={local.loadingLabel}\n type={local.type ?? \"button\"}\n class={`k2b-copy-button ${local.class ?? \"\"}`}\n size={local.size ?? \"sm\"}\n variant={local.variant ?? \"ghost\"}\n aria-label={iconOnly() ? visibleLabel() : undefined}\n onClick={copy}\n >\n <i class={icon()} aria-hidden=\"true\" />\n {!iconOnly() && <span>{visibleLabel()}</span>}\n </Button>\n );\n\n return iconOnly() ? (\n <>\n {button(visibleLabel())}\n <span class=\"k2b-sr-only\" aria-live=\"polite\">\n {copied() ? visibleLabel() : \"\"}\n </span>\n </>\n ) : (\n button(undefined)\n );\n}\n\nexport default CopyButton;\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":[],"sources":["actions/CopyButton.tsx"],"sourcesContent":["import { copyToClipboard } from \"@k2b/stdlib/browser\";\nimport { createSignal, type JSX, onCleanup, splitProps } from \"solid-js\";\nimport { useUiMessages } from \"../intl/messages\";\nimport { Button, type ButtonProps } from \"./Button\";\n\nexport type CopyButtonValue = { text: string; value?: string } | { text?: string; value: string };\n\nexport type CopyButtonProps = CopyButtonValue &\n Omit<ButtonProps, \"children\" | \"onClick\"> & {\n label?: string;\n copiedLabel?: string;\n iconOnly?: boolean;\n onCopied?: () => void;\n onCopyError?: (error: unknown) => void;\n resetAfter?: number;\n };\n\nexport async function copyText(\n text: string,\n onCopyError?: (error: unknown) => void,\n copy: (text: string) => Promise<void> = copyToClipboard,\n): Promise<void> {\n try {\n await copy(text);\n } catch (error) {\n onCopyError?.(error);\n throw error;\n }\n}\n\nexport function CopyButton(props: CopyButtonProps): JSX.Element {\n const messages = useUiMessages();\n const [local, rest] = splitProps(props, [\n \"class\",\n \"copiedLabel\",\n \"disabled\",\n \"iconOnly\",\n \"label\",\n \"loading\",\n \"loadingLabel\",\n \"onCopied\",\n \"onCopyError\",\n \"resetAfter\",\n \"size\",\n \"text\",\n \"type\",\n \"value\",\n \"variant\",\n ]);\n const [copied, setCopied] = createSignal(false);\n let resetTimer: ReturnType<typeof setTimeout> | undefined;\n\n onCleanup(() => {\n if (resetTimer) clearTimeout(resetTimer);\n });\n\n const copy = async () => {\n // `copyText` reports through `onCopyError` and then rethrows so direct\n // callers can await it. The click handler is not awaited by anyone, so it\n // has to absorb the rejection here — otherwise a denied clipboard\n // permission surfaces as an unhandled rejection despite `onCopyError`.\n try {\n await copyText(local.text ?? local.value ?? \"\", local.onCopyError);\n } catch {\n return;\n }\n setCopied(true);\n local.onCopied?.();\n if (resetTimer) clearTimeout(resetTimer);\n resetTimer = setTimeout(() => setCopied(false), local.resetAfter ?? 2000);\n };\n\n const copyLabel = () => local.label ?? messages().copy;\n const copiedLabel = () => local.copiedLabel ?? messages().copied;\n const visibleLabel = () => (copied() ? copiedLabel() : copyLabel());\n const icon = () => (copied() ? \"ti ti-check\" : \"ti ti-copy\");\n const iconOnly = () => local.iconOnly ?? local.label === undefined;\n // Copied often flashes into a row next to a field; the other label, drawn hidden by CSS, keeps the button's width.\n const hiddenLabel = () => (copied() ? copyLabel() : copiedLabel());\n const announcement = () => (\n <span class=\"k2b-sr-only\" aria-live=\"polite\">\n {copied() ? visibleLabel() : \"\"}\n </span>\n );\n const button = (tooltip?: string) => (\n <Button\n {...rest}\n tooltip={tooltip}\n disabled={local.disabled}\n loading={local.loading}\n loadingLabel={local.loadingLabel}\n type={local.type ?? \"button\"}\n class={`k2b-copy-button ${local.class ?? \"\"}`}\n size={local.size ?? \"sm\"}\n variant={local.variant ?? \"ghost\"}\n aria-label={iconOnly() ? visibleLabel() : undefined}\n onClick={copy}\n >\n <i class={icon()} aria-hidden=\"true\" />\n {!iconOnly() && (\n <span class=\"k2b-copy-button__label\" data-reserve={hiddenLabel()}>\n <span>{visibleLabel()}</span>\n </span>\n )}\n </Button>\n );\n\n return (\n <>\n {button(iconOnly() ? visibleLabel() : undefined)}\n {announcement()}\n </>\n );\n}\n\nexport default CopyButton;\n"],"mappings":"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","ignoreList":[]}
@@ -23,8 +23,11 @@ import { resolvePromptMessages } from "./prompt-messages";
23
23
 
24
24
  const PHRASE_SLOT = "\u0000";
25
25
 
26
- /** A prompt's `variant` is its tone too: a success or danger prompt carries the dialog tone of that name. */
27
- export const promptTone = variant => variant === "success" || variant === "danger" ? variant : undefined;
26
+ /** A prompt's `variant` is its tone too: a success, warning or danger prompt carries the dialog tone of that name. */
27
+ export const promptTone = variant => variant === "primary" ? undefined : variant;
28
+
29
+ /** A warning asks for care, not for a destructive act: its confirm button stays primary. */
30
+ export const promptButtonVariant = variant => variant === undefined || variant === "warning" ? "primary" : variant;
28
31
  export const DialogHeader = props => _$ssr(_tmpl$, _$escape(_$createComponent(Show, {
29
32
  get when() {
30
33
  return _$memo(() => !!props.tone)() ? dialogToneIcon(props.tone) : props.icon;
@@ -69,7 +72,7 @@ export const confirmPrompt = (content, options) => {
69
72
  return promptTone(options?.variant);
70
73
  },
71
74
  close: () => close(false)
72
- })), _$escape(content), _$escape(options?.cancelText || resolveUiMessages().cancel), _$ssrAttribute("data-variant", _$escape(options?.variant ?? "primary", true), false), _$escape(options?.confirmText || resolvePromptMessages().confirm));
75
+ })), _$escape(content), _$escape(options?.cancelText || resolveUiMessages().cancel), _$ssrAttribute("data-variant", _$escape(promptButtonVariant(options?.variant), true), false), _$escape(options?.confirmText || resolvePromptMessages().confirm));
73
76
  }
74
77
 
75
78
  // The catalog owns word order; the slot marks where the verbatim phrase is rendered as code.
@@ -104,7 +107,7 @@ export const confirmPrompt = (content, options) => {
104
107
  spellcheck: false,
105
108
  monospace: true,
106
109
  required: true
107
- })), _$escape(options?.cancelText || resolveUiMessages().cancel), _$ssrAttribute("data-variant", _$escape(options?.variant ?? "primary", true), false), _$ssrAttribute("disabled", !canConfirm(), true), _$escape(options?.confirmText || resolvePromptMessages().confirm));
110
+ })), _$escape(options?.cancelText || resolveUiMessages().cancel), _$ssrAttribute("data-variant", _$escape(promptButtonVariant(options?.variant), true), false), _$ssrAttribute("disabled", !canConfirm(), true), _$escape(options?.confirmText || resolvePromptMessages().confirm));
108
111
  }, {
109
112
  panelClassName: panelClass(options),
110
113
  contentClassName: contentClass(options?.surface),
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["feedback/prompt-confirm.tsx"],"sourcesContent":["import { createSignal, type JSX, Show } from \"solid-js\";\nimport { TextInput } from \"../inputs/TextInput\";\nimport { resolveUiMessages } from \"../intl/messages\";\nimport { dialogCore } from \"./dialog-core\";\nimport { type DialogTone, dialogToneIcon, dialogToneLabel } from \"./dialog-tone\";\nimport { resolvePromptMessages } from \"./prompt-messages\";\nimport type { ConfirmOptions, DialogOptions } from \"./prompts\";\n\n// The dialog frame and `prompts.confirm`, apart from the form prompts: `PanelDialog` asks before discarding changes,\n// and the form prompts render date pickers whose phone sheet is a `PanelDialog`, so one module would be an import cycle.\n\nexport type PromptContent = string | HTMLElement | JSX.Element;\n\nconst PHRASE_SLOT = \"\\u0000\";\n\n/** A prompt's `variant` is its tone too: a success or danger prompt carries the dialog tone of that name. */\nexport const promptTone = (variant: DialogOptions[\"variant\"]): DialogTone | undefined =>\n variant === \"success\" || variant === \"danger\" ? variant : undefined;\n\nexport const DialogHeader = (props: { close: () => void; title?: string; icon?: string; tone?: DialogTone }): JSX.Element => (\n <header class=\"k2b-dialog__header\">\n <Show when={props.tone ? dialogToneIcon(props.tone) : props.icon}>\n {(icon) => <i class={icon()} data-tone={props.tone} aria-hidden=\"true\" />}\n </Show>\n <Show when={props.tone}>\n {(tone) => (\n <span class=\"k2b-sr-only\" data-dialog-tone-label>\n {dialogToneLabel(resolveUiMessages(), tone())}\n </span>\n )}\n </Show>\n <Show when={props.title} fallback={<span class=\"k2b-dialog__header-spacer\" />}>\n {(title) => <h2>{title()}</h2>}\n </Show>\n <button type=\"button\" class=\"k2b-dialog__close\" aria-label={resolveUiMessages().closeDialog} onClick={props.close}>\n <i class=\"ti ti-x\" aria-hidden=\"true\" />\n </button>\n </header>\n);\n\nexport const panelClass = (options?: Pick<DialogOptions, \"size\" | \"surface\" | \"variant\">): string => {\n const size = options?.size ?? \"medium\";\n const variant = options?.variant && options.variant !== \"primary\" ? ` k2b-dialog--${options.variant}` : \"\";\n return `k2b-dialog k2b-dialog--${size}${variant}${options?.surface === \"bare\" ? \" is-bare\" : \"\"}`;\n};\n\nexport const contentClass = (surface?: DialogOptions[\"surface\"]): string =>\n surface === \"bare\" ? \"k2b-dialog__viewport is-bare\" : \"k2b-dialog__viewport\";\n\nexport const confirmPrompt = (content: PromptContent, options?: ConfirmOptions): Promise<boolean | undefined> => {\n const confirmationPhrase = options?.confirmationPhrase;\n if (confirmationPhrase !== undefined && (confirmationPhrase.trim().length === 0 || /[\\r\\n\\t]/.test(confirmationPhrase))) {\n throw new Error(\"confirmationPhrase must be non-empty, visible, and single-line\");\n }\n let confirmationInput: HTMLInputElement | undefined;\n\n return dialogCore.open<boolean>(\n (close) => {\n if (!confirmationPhrase) {\n return (\n <div class=\"k2b-dialog__panel\">\n <DialogHeader title={options?.title} icon={options?.icon} tone={promptTone(options?.variant)} close={() => close(false)} />\n <div class=\"k2b-dialog__body\">{content}</div>\n <footer class=\"k2b-dialog__actions\">\n <button type=\"button\" class=\"k2b-button\" data-variant=\"secondary\" onClick={() => close(false)}>\n {options?.cancelText || resolveUiMessages().cancel}\n </button>\n <button type=\"button\" class=\"k2b-button\" data-variant={options?.variant ?? \"primary\"} onClick={() => close(true)}>\n {options?.confirmText || resolvePromptMessages().confirm}\n </button>\n </footer>\n </div>\n );\n }\n\n // The catalog owns word order; the slot marks where the verbatim phrase is rendered as code.\n const [labelBefore, labelAfter] = resolvePromptMessages().typeToConfirm({ phrase: PHRASE_SLOT }).split(PHRASE_SLOT);\n const [confirmationValue, setConfirmationValue] = createSignal(\"\");\n const canConfirm = () => confirmationValue() === confirmationPhrase;\n const submit = (event: SubmitEvent) => {\n event.preventDefault();\n if (canConfirm()) close(true);\n };\n\n return (\n <form class=\"k2b-dialog__panel\" onSubmit={submit}>\n <DialogHeader title={options?.title} icon={options?.icon} tone={promptTone(options?.variant)} close={() => close(false)} />\n <div class=\"k2b-dialog__body k2b-prompt-form\">\n <div class=\"k2b-prompt-copy\">{content}</div>\n <TextInput\n ref={(element) => {\n confirmationInput = element;\n }}\n label={\n <>\n {labelBefore}\n <code class=\"k2b-confirmation-phrase\">{confirmationPhrase}</code>\n {labelAfter}\n </>\n }\n value={confirmationValue}\n onValueChange={setConfirmationValue}\n autocomplete=\"off\"\n autocapitalize=\"off\"\n spellcheck={false}\n monospace\n required\n />\n </div>\n <footer class=\"k2b-dialog__actions\">\n <button type=\"button\" class=\"k2b-button\" data-variant=\"secondary\" onClick={() => close(false)}>\n {options?.cancelText || resolveUiMessages().cancel}\n </button>\n <button type=\"submit\" class=\"k2b-button\" data-variant={options?.variant ?? \"primary\"} disabled={!canConfirm()}>\n {options?.confirmText || resolvePromptMessages().confirm}\n </button>\n </footer>\n </form>\n );\n },\n {\n panelClassName: panelClass(options),\n contentClassName: contentClass(options?.surface),\n initialFocus: confirmationPhrase ? () => confirmationInput ?? null : undefined,\n signal: options?.signal,\n cancelBehavior: options?.cancelBehavior,\n history: options?.history,\n ariaLabel: options?.ariaLabel ?? options?.title ?? resolvePromptMessages().confirmation,\n },\n );\n};\n\n/** `prompts` starts as this object; `PanelDialog` asks through it, so it reaches a replaced `prompts.confirm` too. */\nexport const sharedPrompts = { confirm: confirmPrompt };\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":[],"sources":["feedback/prompt-confirm.tsx"],"sourcesContent":["import { createSignal, type JSX, Show } from \"solid-js\";\nimport { TextInput } from \"../inputs/TextInput\";\nimport { resolveUiMessages } from \"../intl/messages\";\nimport { dialogCore } from \"./dialog-core\";\nimport { type DialogTone, dialogToneIcon, dialogToneLabel } from \"./dialog-tone\";\nimport { resolvePromptMessages } from \"./prompt-messages\";\nimport type { ConfirmOptions, DialogOptions } from \"./prompts\";\n\n// The dialog frame and `prompts.confirm`, apart from the form prompts: `PanelDialog` asks before discarding changes,\n// and the form prompts render date pickers whose phone sheet is a `PanelDialog`, so one module would be an import cycle.\n\nexport type PromptContent = string | HTMLElement | JSX.Element;\n\nconst PHRASE_SLOT = \"\\u0000\";\n\n/** A prompt's `variant` is its tone too: a success, warning or danger prompt carries the dialog tone of that name. */\nexport const promptTone = (variant: DialogOptions[\"variant\"]): DialogTone | undefined => (variant === \"primary\" ? undefined : variant);\n\n/** A warning asks for care, not for a destructive act: its confirm button stays primary. */\nexport const promptButtonVariant = (variant: DialogOptions[\"variant\"]): \"danger\" | \"primary\" | \"success\" =>\n variant === undefined || variant === \"warning\" ? \"primary\" : variant;\n\nexport const DialogHeader = (props: { close: () => void; title?: string; icon?: string; tone?: DialogTone }): JSX.Element => (\n <header class=\"k2b-dialog__header\">\n <Show when={props.tone ? dialogToneIcon(props.tone) : props.icon}>\n {(icon) => <i class={icon()} data-tone={props.tone} aria-hidden=\"true\" />}\n </Show>\n <Show when={props.tone}>\n {(tone) => (\n <span class=\"k2b-sr-only\" data-dialog-tone-label>\n {dialogToneLabel(resolveUiMessages(), tone())}\n </span>\n )}\n </Show>\n <Show when={props.title} fallback={<span class=\"k2b-dialog__header-spacer\" />}>\n {(title) => <h2>{title()}</h2>}\n </Show>\n <button type=\"button\" class=\"k2b-dialog__close\" aria-label={resolveUiMessages().closeDialog} onClick={props.close}>\n <i class=\"ti ti-x\" aria-hidden=\"true\" />\n </button>\n </header>\n);\n\nexport const panelClass = (options?: Pick<DialogOptions, \"size\" | \"surface\" | \"variant\">): string => {\n const size = options?.size ?? \"medium\";\n const variant = options?.variant && options.variant !== \"primary\" ? ` k2b-dialog--${options.variant}` : \"\";\n return `k2b-dialog k2b-dialog--${size}${variant}${options?.surface === \"bare\" ? \" is-bare\" : \"\"}`;\n};\n\nexport const contentClass = (surface?: DialogOptions[\"surface\"]): string =>\n surface === \"bare\" ? \"k2b-dialog__viewport is-bare\" : \"k2b-dialog__viewport\";\n\nexport const confirmPrompt = (content: PromptContent, options?: ConfirmOptions): Promise<boolean | undefined> => {\n const confirmationPhrase = options?.confirmationPhrase;\n if (confirmationPhrase !== undefined && (confirmationPhrase.trim().length === 0 || /[\\r\\n\\t]/.test(confirmationPhrase))) {\n throw new Error(\"confirmationPhrase must be non-empty, visible, and single-line\");\n }\n let confirmationInput: HTMLInputElement | undefined;\n\n return dialogCore.open<boolean>(\n (close) => {\n if (!confirmationPhrase) {\n return (\n <div class=\"k2b-dialog__panel\">\n <DialogHeader title={options?.title} icon={options?.icon} tone={promptTone(options?.variant)} close={() => close(false)} />\n <div class=\"k2b-dialog__body\">{content}</div>\n <footer class=\"k2b-dialog__actions\">\n <button type=\"button\" class=\"k2b-button\" data-variant=\"secondary\" onClick={() => close(false)}>\n {options?.cancelText || resolveUiMessages().cancel}\n </button>\n <button type=\"button\" class=\"k2b-button\" data-variant={promptButtonVariant(options?.variant)} onClick={() => close(true)}>\n {options?.confirmText || resolvePromptMessages().confirm}\n </button>\n </footer>\n </div>\n );\n }\n\n // The catalog owns word order; the slot marks where the verbatim phrase is rendered as code.\n const [labelBefore, labelAfter] = resolvePromptMessages().typeToConfirm({ phrase: PHRASE_SLOT }).split(PHRASE_SLOT);\n const [confirmationValue, setConfirmationValue] = createSignal(\"\");\n const canConfirm = () => confirmationValue() === confirmationPhrase;\n const submit = (event: SubmitEvent) => {\n event.preventDefault();\n if (canConfirm()) close(true);\n };\n\n return (\n <form class=\"k2b-dialog__panel\" onSubmit={submit}>\n <DialogHeader title={options?.title} icon={options?.icon} tone={promptTone(options?.variant)} close={() => close(false)} />\n <div class=\"k2b-dialog__body k2b-prompt-form\">\n <div class=\"k2b-prompt-copy\">{content}</div>\n <TextInput\n ref={(element) => {\n confirmationInput = element;\n }}\n label={\n <>\n {labelBefore}\n <code class=\"k2b-confirmation-phrase\">{confirmationPhrase}</code>\n {labelAfter}\n </>\n }\n value={confirmationValue}\n onValueChange={setConfirmationValue}\n autocomplete=\"off\"\n autocapitalize=\"off\"\n spellcheck={false}\n monospace\n required\n />\n </div>\n <footer class=\"k2b-dialog__actions\">\n <button type=\"button\" class=\"k2b-button\" data-variant=\"secondary\" onClick={() => close(false)}>\n {options?.cancelText || resolveUiMessages().cancel}\n </button>\n <button type=\"submit\" class=\"k2b-button\" data-variant={promptButtonVariant(options?.variant)} disabled={!canConfirm()}>\n {options?.confirmText || resolvePromptMessages().confirm}\n </button>\n </footer>\n </form>\n );\n },\n {\n panelClassName: panelClass(options),\n contentClassName: contentClass(options?.surface),\n initialFocus: confirmationPhrase ? () => confirmationInput ?? null : undefined,\n signal: options?.signal,\n cancelBehavior: options?.cancelBehavior,\n history: options?.history,\n ariaLabel: options?.ariaLabel ?? options?.title ?? resolvePromptMessages().confirmation,\n },\n );\n};\n\n/** `prompts` starts as this object; `PanelDialog` asks through it, so it reaches a replaced `prompts.confirm` too. */\nexport const sharedPrompts = { confirm: confirmPrompt };\n"],"mappings":"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","ignoreList":[]}
@@ -39,7 +39,7 @@ import { TextInput } from "../inputs/TextInput";
39
39
  import { KeyedFor } from "../internal/keyed-for";
40
40
  import { resolveUiMessages } from "../intl/messages";
41
41
  import { dialogCore } from "./dialog-core";
42
- import { contentClass, DialogHeader, panelClass, promptTone, sharedPrompts } from "./prompt-confirm";
42
+ import { contentClass, DialogHeader, panelClass, promptButtonVariant, promptTone, sharedPrompts } from "./prompt-confirm";
43
43
  import { resolvePromptMessages } from "./prompt-messages";
44
44
  export { DialogHeader } from "./prompt-confirm";
45
45
  const isEmpty = value => value === undefined || value === null || value === "" || Array.isArray(value) && value.length === 0;
@@ -380,7 +380,7 @@ const PromptFormDialog = props => {
380
380
  get children() {
381
381
  return _$ssr(_tmpl$2, _$escape(props.config.cancelText || resolveUiMessages().cancel));
382
382
  }
383
- })), _$ssrAttribute("data-variant", _$escape(props.config.variant ?? "primary", true), false), _$escape(props.config.confirmText ?? resolveUiMessages().save));
383
+ })), _$ssrAttribute("data-variant", _$escape(promptButtonVariant(props.config.variant), true), false), _$escape(props.config.confirmText ?? resolveUiMessages().save));
384
384
  };
385
385
 
386
386
  // Results without an ID keep today's behavior: each object is its own identity, so a new answer replaces the row.
@@ -604,7 +604,7 @@ export const prompts = Object.assign(sharedPrompts, {
604
604
  return promptTone(options?.variant);
605
605
  },
606
606
  close: () => close()
607
- })), _$escape(content), _$ssrAttribute("data-variant", _$escape(options?.variant ?? "primary", true), false), _$escape(options?.confirmText || resolveUiMessages().ok)), {
607
+ })), _$escape(content), _$ssrAttribute("data-variant", _$escape(promptButtonVariant(options?.variant), true), false), _$escape(options?.confirmText || resolveUiMessages().ok)), {
608
608
  panelClassName: panelClass(options),
609
609
  contentClassName: contentClass(options?.surface),
610
610
  signal: options?.signal,
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["feedback/prompts.tsx"],"sourcesContent":["import { mutation, timed } from \"@k2b/stdlib/solid\";\nimport { createEffect, createMemo, createSignal, createUniqueId, For, type JSX, onCleanup, Show } from \"solid-js\";\nimport { createStore } from \"solid-js/store\";\nimport { Checkbox } from \"../inputs/Checkbox\";\nimport { PinInput } from \"../inputs/ChoiceInputs\";\nimport { DatePicker, DateTimePicker } from \"../inputs/DatePicker\";\nimport { ImageInput } from \"../inputs/FileInputs\";\nimport { NumberInput } from \"../inputs/NumberInput\";\nimport { Select } from \"../inputs/Select\";\nimport { resolveSelectMessages } from \"../inputs/select-messages\";\nimport { TagsInput } from \"../inputs/TagsInput\";\nimport { TextInput } from \"../inputs/TextInput\";\nimport { KeyedFor } from \"../internal/keyed-for\";\nimport { resolveUiMessages } from \"../intl/messages\";\nimport { type DialogRender, dialogCore, type OpenDialogOptions } from \"./dialog-core\";\nimport { contentClass, DialogHeader, type PromptContent, panelClass, promptTone, sharedPrompts } from \"./prompt-confirm\";\nimport { resolvePromptMessages } from \"./prompt-messages\";\n\nexport { DialogHeader } from \"./prompt-confirm\";\n\nexport interface DialogOptions {\n signal?: AbortSignal;\n title?: string;\n ariaLabel?: string;\n icon?: string;\n confirmText?: string;\n cancelText?: string | false;\n variant?: \"danger\" | \"primary\" | \"success\";\n /** `full` fills the available viewport and becomes edge-to-edge on narrow screens. */\n size?: \"small\" | \"medium\" | \"large\" | \"wide\" | \"full\";\n surface?: \"default\" | \"bare\";\n header?: false;\n cancelBehavior?: OpenDialogOptions[\"cancelBehavior\"];\n /** Back closes the prompt like Cancel, as in a phone app; see `OpenDialogOptions.history`. */\n history?: boolean;\n}\n\nexport interface ConfirmOptions extends DialogOptions {\n confirmationPhrase?: string;\n}\n\nexport type PromptSearchItem<T = unknown> = {\n /**\n * Stable identity of the result, such as its record ID. With it, a newer answer that contains the same result keeps\n * its row, so a click in progress still lands. Without it, each answer replaces the rows.\n */\n id?: string;\n label: string;\n desc?: string;\n icon?: string;\n previewUrl?: string;\n value?: T;\n};\n\nexport type PromptSearchInput = {\n query: string;\n abortSignal: AbortSignal;\n};\n\nexport type PromptSearchOptions = DialogOptions & {\n placeholder?: string;\n icon?: string;\n initialQuery?: string;\n minQueryLength?: number;\n debounceMs?: number;\n emptyText?: string;\n noResultsText?: string;\n};\n\nexport type PromptFieldBase<T = any> = {\n label?: string | false;\n description?: string;\n placeholder?: string;\n required?: boolean;\n default?: T;\n validate?: (value: T | undefined) => string | null;\n};\n\nexport type FieldSchema =\n | (PromptFieldBase<string> & {\n type: \"text\";\n multiline?: boolean;\n lines?: number;\n maxLength?: number;\n minLength?: number;\n icon?: string;\n activeIcon?: string;\n password?: boolean;\n markdown?: boolean;\n })\n | (PromptFieldBase<number> & {\n type: \"number\";\n min?: number;\n max?: number;\n step?: number;\n })\n | (PromptFieldBase<string> & {\n type: \"image\";\n round?: boolean;\n ariaLabel?: string;\n accept?: string;\n })\n | (PromptFieldBase<string> & {\n type: \"pin\";\n length?: number;\n stretch?: boolean;\n })\n | (PromptFieldBase<string> & {\n type: \"select\";\n options: string[] | { id: string; label?: string; description?: string; icon?: string }[];\n icon?: string;\n activeIcon?: string;\n clearable?: boolean;\n })\n | (PromptFieldBase<string[]> & {\n type: \"tags\";\n maxTags?: number;\n minTags?: number;\n icon?: string;\n activeIcon?: string;\n })\n | (PromptFieldBase<boolean> & {\n type: \"boolean\";\n })\n | (PromptFieldBase<string> & {\n type: \"datetime\";\n dateOnly?: boolean;\n /** A date whose time is optional, as `DateTimePicker`'s `optionalTime`. */\n optionalTime?: boolean;\n })\n | {\n type: \"info\";\n content: string | JSX.Element | (() => JSX.Element);\n };\n\ntype InferFieldType<T extends FieldSchema> = T extends { type: \"text\" }\n ? string\n : T extends { type: \"number\" }\n ? number\n : T extends { type: \"image\" }\n ? string\n : T extends { type: \"pin\" }\n ? string\n : T extends { type: \"select\" }\n ? string\n : T extends { type: \"tags\" }\n ? string[]\n : T extends { type: \"boolean\" }\n ? boolean\n : T extends { type: \"datetime\" }\n ? string\n : T extends { type: \"currency\" }\n ? number\n : T extends { type: \"info\" }\n ? never\n : never;\n\ntype InferFormValues<T extends Record<string, FieldSchema>> = {\n [K in keyof T as T[K] extends { type: \"info\" } ? never : K]: T[K] extends { required: true }\n ? InferFieldType<T[K]>\n : InferFieldType<T[K]> | undefined;\n};\n\ntype PromptFormValue = string | number | boolean | string[] | undefined;\ntype PromptFormOptions<T extends Record<string, FieldSchema>> = {\n signal?: AbortSignal;\n title?: string;\n ariaLabel?: string;\n icon?: string;\n fields: T;\n confirmText?: string;\n cancelText?: string | false;\n variant?: \"danger\" | \"primary\" | \"success\";\n size?: DialogOptions[\"size\"];\n cancelBehavior?: DialogOptions[\"cancelBehavior\"];\n};\n\nconst isEmpty = (value: unknown): boolean =>\n value === undefined || value === null || value === \"\" || (Array.isArray(value) && value.length === 0);\n\nexport const createFormState = <T extends Record<string, FieldSchema>>(schema: T) => {\n const messages = resolveUiMessages();\n const promptMessages = resolvePromptMessages();\n const [values, setValues] = createStore<Record<string, PromptFormValue>>({});\n const [errors, setErrors] = createStore<Record<string, string | undefined>>({});\n // Errors appear with the first submit and then follow every change. Before that, a check that fails mid-input,\n // such as a URL still being typed, would interrupt the user with an alert on the first character.\n let submitted = false;\n\n for (const [key, field] of Object.entries(schema)) {\n if (field.type !== \"info\" && \"default\" in field) setValues(key, field.default as PromptFormValue);\n }\n\n const validateField = (key: string, value: PromptFormValue): string | null => {\n const field = schema[key];\n if (!field || field.type === \"info\") return null;\n if (field.type === \"boolean\" && field.required && value !== true) return messages.required;\n if (field.required && isEmpty(value)) return messages.required;\n if (\"validate\" in field && field.validate) {\n const customError = (field.validate as (next: never) => string | null)(value as never);\n if (customError) return customError;\n }\n if (field.type === \"text\" && typeof value === \"string\" && value.length > 0) {\n if (field.minLength !== undefined && value.length < field.minLength) return promptMessages.minCharacters({ count: field.minLength });\n if (field.maxLength !== undefined && value.length > field.maxLength) return promptMessages.maxCharacters({ count: field.maxLength });\n }\n if (field.type === \"tags\" && Array.isArray(value) && value.length > 0) {\n if (field.minTags !== undefined && value.length < field.minTags) return promptMessages.minTags({ count: field.minTags });\n if (field.maxTags !== undefined && value.length > field.maxTags) return promptMessages.maxTags({ count: field.maxTags });\n }\n return null;\n };\n\n const updateField = (key: string, value: PromptFormValue) => {\n setValues(key, value);\n if (submitted) setErrors(key, validateField(key, value) ?? undefined);\n };\n\n const validateAll = (): boolean => {\n submitted = true;\n let valid = true;\n for (const [key, field] of Object.entries(schema)) {\n if (field.type === \"info\") continue;\n const error = validateField(key, values[key]);\n setErrors(key, error ?? undefined);\n if (error) valid = false;\n }\n return valid;\n };\n\n const reset = () => {\n submitted = false;\n for (const [key, field] of Object.entries(schema)) {\n if (field.type === \"info\") continue;\n setValues(key, \"default\" in field ? (field.default as PromptFormValue) : undefined);\n setErrors(key, undefined);\n }\n };\n\n return { values, errors, updateField, validateAll, reset };\n};\n\nconst renderInfo = (content: Extract<FieldSchema, { type: \"info\" }>[\"content\"]): JSX.Element => {\n if (typeof content === \"string\") return <p>{content}</p>;\n if (typeof content === \"function\") return content();\n return content;\n};\n\nconst PromptControl = (props: {\n field: Exclude<FieldSchema, { type: \"info\" }>;\n value: () => PromptFormValue;\n update: (value: PromptFormValue) => void;\n error: () => string | undefined;\n submit: () => void;\n}): JSX.Element => {\n const label = props.field.label || undefined;\n\n switch (props.field.type) {\n case \"text\":\n return (\n <TextInput\n label={label}\n description={props.field.description}\n required={props.field.required}\n placeholder={props.field.placeholder}\n error={props.error}\n value={String(props.value() ?? \"\")}\n onValueChange={(value) => props.update(value ?? undefined)}\n onSubmit={props.submit}\n multiline={props.field.multiline}\n lines={props.field.lines}\n icon={props.field.icon}\n activeIcon={props.field.activeIcon}\n password={props.field.password}\n markdown={props.field.markdown}\n minLength={props.field.minLength}\n maxLength={props.field.maxLength}\n />\n );\n case \"number\":\n return (\n <NumberInput\n label={label}\n description={props.field.description}\n required={props.field.required}\n placeholder={props.field.placeholder}\n error={props.error}\n value={typeof props.value() === \"number\" ? (props.value() as number) : null}\n onValueChange={(value) => props.update(value ?? undefined)}\n min={props.field.min}\n max={props.field.max}\n step={props.field.step}\n />\n );\n case \"image\":\n return (\n <ImageInput\n label={label}\n description={props.field.description}\n required={props.field.required}\n error={props.error}\n value={() => (typeof props.value() === \"string\" ? (props.value() as string) : null)}\n onValueChange={(value) => props.update(value ?? undefined)}\n round={props.field.round}\n aria-label={props.field.ariaLabel}\n accept={props.field.accept}\n />\n );\n case \"pin\":\n return (\n <PinInput\n label={label}\n description={props.field.description}\n required={props.field.required}\n error={props.error}\n value={() => String(props.value() ?? \"\")}\n onValueChange={props.update}\n length={props.field.length}\n stretch={props.field.stretch}\n />\n );\n case \"select\":\n return (\n <Select\n label={label}\n description={props.field.description}\n required={props.field.required}\n placeholder={props.field.placeholder}\n error={props.error}\n value={() => (typeof props.value() === \"string\" ? (props.value() as string) : null)}\n onValueChange={(value) => props.update(value ?? undefined)}\n options={props.field.options}\n icon={props.field.icon}\n activeIcon={props.field.activeIcon}\n clearable={props.field.clearable}\n />\n );\n case \"tags\":\n return (\n <TagsInput\n label={label}\n description={props.field.description}\n required={props.field.required}\n placeholder={props.field.placeholder}\n error={props.error}\n value={() => (Array.isArray(props.value()) ? (props.value() as string[]) : [])}\n onValueChange={props.update}\n maxTags={props.field.maxTags}\n icon={props.field.icon}\n activeIcon={props.field.activeIcon}\n />\n );\n case \"boolean\":\n return (\n <Checkbox\n label={label}\n description={props.field.description}\n required={props.field.required}\n error={props.error}\n value={() => Boolean(props.value())}\n onValueChange={props.update}\n />\n );\n case \"datetime\": {\n const pickerProps = {\n label,\n description: props.field.description,\n required: props.field.required,\n placeholder: props.field.placeholder,\n error: props.error,\n value: () => (typeof props.value() === \"string\" ? (props.value() as string) : null),\n onValueChange: (value: string | null) => props.update(value ?? \"\"),\n clearable: true,\n };\n return props.field.dateOnly ? (\n <DatePicker {...pickerProps} />\n ) : (\n <DateTimePicker {...pickerProps} optionalTime={props.field.optionalTime} />\n );\n }\n }\n};\n\nconst PromptFormDialog = <T extends Record<string, FieldSchema>>(props: {\n config: PromptFormOptions<T>;\n close: (value: InferFormValues<T> | null) => void;\n}): JSX.Element => {\n const state = createFormState(props.config.fields);\n const submit = () => {\n if (state.validateAll()) props.close(state.values as InferFormValues<T>);\n };\n const handleSubmit = (event: SubmitEvent) => {\n event.preventDefault();\n submit();\n };\n\n return (\n <form class=\"k2b-dialog__panel\" onSubmit={handleSubmit}>\n <DialogHeader\n title={props.config.title}\n icon={props.config.icon}\n tone={promptTone(props.config.variant)}\n close={() => props.close(null)}\n />\n <div class=\"k2b-dialog__body k2b-prompt-form\">\n <For each={Object.entries(props.config.fields)}>\n {([key, field]) => {\n if (field.type === \"info\") return <div class=\"k2b-prompt-form__info\">{renderInfo(field.content)}</div>;\n return (\n <PromptControl\n field={field}\n value={() => state.values[key]}\n update={(value) => state.updateField(key, value)}\n error={() => state.errors[key]}\n submit={submit}\n />\n );\n }}\n </For>\n </div>\n <footer class=\"k2b-dialog__actions\">\n <Show when={props.config.cancelText !== false}>\n <button type=\"button\" class=\"k2b-button\" data-variant=\"secondary\" onClick={() => props.close(null)}>\n {props.config.cancelText || resolveUiMessages().cancel}\n </button>\n </Show>\n <button type=\"submit\" class=\"k2b-button\" data-variant={props.config.variant ?? \"primary\"}>\n {props.config.confirmText ?? resolveUiMessages().save}\n </button>\n </footer>\n </form>\n );\n};\n\n// Results without an ID keep today's behavior: each object is its own identity, so a new answer replaces the row.\nconst anonymousRows = new WeakMap<object, string>();\nlet anonymousRow = 0;\nconst searchRowIdentity = (item: PromptSearchItem<unknown>): string => {\n if (item.id !== undefined) return `id:${item.id}`;\n const known = anonymousRows.get(item);\n if (known !== undefined) return known;\n const key = `object:${anonymousRow++}`;\n anonymousRows.set(item, key);\n return key;\n};\n\ntype CloudSearchResolver<T> = (input: PromptSearchInput) => Promise<PromptSearchItem<T>[]> | PromptSearchItem<T>[];\n\nconst openSearchPrompt = <T extends unknown = unknown>(resolver: CloudSearchResolver<T>, options?: PromptSearchOptions) =>\n dialogCore.open<PromptSearchItem<T>>(\n (close) => {\n const [query, setQuery] = createSignal(options?.initialQuery ?? \"\");\n const [items, setItems] = createSignal<PromptSearchItem<T>[]>([]);\n const [activeIndex, setActiveIndex] = createSignal(0);\n const [hasLoaded, setHasLoaded] = createSignal(false);\n const [failedPreviews, setFailedPreviews] = createStore<Record<number, true>>({});\n const [activeSearchQuery, setActiveSearchQuery] = createSignal(\"\");\n const rowRefs = new Map<number, HTMLButtonElement>();\n const searchId = `k2b-prompt-search-${createUniqueId()}`;\n const listboxId = `${searchId}-listbox`;\n const optionId = (index: number) => `${searchId}-option-${index}`;\n\n const minQueryLength = options?.minQueryLength ?? 0;\n const debounceMs = options?.debounceMs ?? 180;\n const searchMutation = mutation.create<{ query: string; items: PromptSearchItem<T>[] }, string, { requestQuery: string }>({\n onBefore: (requestQuery) => ({ requestQuery }),\n mutation: async (requestQuery, context) => {\n const result = await resolver({\n query: requestQuery,\n abortSignal: context.abortSignal,\n });\n return { query: requestQuery, items: (result ?? []).slice() };\n },\n onSuccess: (result, context) => {\n if (!context || context.requestQuery !== activeSearchQuery()) return;\n setItems(result.items);\n setActiveIndex(0);\n setHasLoaded(true);\n },\n onError: (error, context) => {\n if (!context || context.requestQuery !== activeSearchQuery() || error.name === \"AbortError\") return;\n setItems([]);\n setActiveIndex(0);\n setHasLoaded(true);\n },\n });\n const searchError = createMemo(() => {\n const error = searchMutation.error();\n if (!error || error.name === \"AbortError\") return null;\n return error.message || resolvePromptMessages().searchFailed;\n });\n const shouldShowResults = createMemo(() => {\n if (query().trim().length < minQueryLength) return false;\n return hasLoaded() || searchError() !== null || items().length > 0;\n });\n const emptyStateText = createMemo(() => {\n if (!hasLoaded()) return options?.emptyText ?? resolveSelectMessages().typeToSearch;\n return options?.noResultsText ?? resolveUiMessages().noResults;\n });\n const { debouncedFn: debounceSearch, cancel: cancelDebounce } = timed.debounce((nextQuery: string) => {\n setActiveSearchQuery(nextQuery);\n searchMutation.abort();\n void searchMutation.mutate(nextQuery);\n }, debounceMs);\n\n const execute = (item?: PromptSearchItem<T>) => {\n if (!item) return;\n close(item);\n };\n const moveSelection = (delta: -1 | 1) => {\n const list = items();\n if (list.length === 0) return;\n setActiveIndex((activeIndex() + delta + list.length) % list.length);\n };\n\n createEffect(() => {\n const list = items();\n const maxIndex = list.length - 1;\n if (maxIndex < 0) {\n setActiveIndex(0);\n return;\n }\n if (activeIndex() > maxIndex) setActiveIndex(maxIndex);\n rowRefs.get(activeIndex())?.scrollIntoView({ block: \"nearest\" });\n });\n createEffect(() => {\n const nextQuery = query().trim();\n setFailedPreviews({});\n if (nextQuery.length < minQueryLength) {\n cancelDebounce();\n searchMutation.abort();\n setItems([]);\n setActiveIndex(0);\n setHasLoaded(false);\n setActiveSearchQuery(\"\");\n return;\n }\n debounceSearch(nextQuery);\n });\n onCleanup(() => {\n cancelDebounce();\n searchMutation.abort();\n });\n\n return (\n <div class=\"k2b-prompt-search-shell\">\n <Show when={options?.title}>{(title) => <p class=\"k2b-prompt-search-shell__title\">{title()}</p>}</Show>\n <div class=\"k2b-prompt-search\">\n <label class=\"k2b-prompt-search__input\">\n <i class={options?.icon ?? \"ti ti-search\"} aria-hidden=\"true\" />\n <input\n id={searchId}\n type=\"search\"\n role=\"combobox\"\n aria-label={options?.ariaLabel ?? options?.title ?? resolveUiMessages().search}\n aria-autocomplete=\"list\"\n aria-controls={listboxId}\n aria-expanded={shouldShowResults()}\n aria-activedescendant={shouldShowResults() && items().length > 0 ? optionId(activeIndex()) : undefined}\n aria-busy={searchMutation.loading()}\n value={query()}\n onInput={(event) => setQuery(event.currentTarget.value)}\n onKeyDown={(event) => {\n if (event.key === \"ArrowDown\") {\n event.preventDefault();\n moveSelection(1);\n } else if (event.key === \"ArrowUp\") {\n event.preventDefault();\n moveSelection(-1);\n } else if (event.key === \"Enter\") {\n event.preventDefault();\n execute(items()[activeIndex()]);\n }\n }}\n placeholder={options?.placeholder ?? resolveUiMessages().search}\n spellcheck={false}\n autocapitalize=\"off\"\n autocomplete=\"off\"\n autocorrect=\"off\"\n />\n <Show when={searchMutation.loading()}>\n <i class=\"ti ti-loader-2 k2b-spin\" aria-hidden=\"true\" />\n </Show>\n </label>\n <div\n class=\"k2b-prompt-search__collapse\"\n style={{\n height: shouldShowResults() ? \"var(--k2b-search-body-max)\" : \"0px\",\n opacity: shouldShowResults() ? \"1\" : \"0\",\n }}\n >\n <div class=\"k2b-prompt-search__results\" onWheel={(event) => event.stopPropagation()}>\n <Show when={searchError()}>\n {(message) => (\n <div class=\"k2b-prompt-search__error\" role=\"status\" aria-live=\"polite\">\n {message()}\n </div>\n )}\n </Show>\n <Show\n when={items().length > 0}\n fallback={\n <p role=\"status\" aria-live=\"polite\">\n {emptyStateText()}\n </p>\n }\n >\n <div id={listboxId} class=\"k2b-prompt-search__list\" role=\"listbox\" aria-label={resolveUiMessages().searchResults}>\n <KeyedFor each={items()} by={searchRowIdentity}>\n {(item, index) => (\n <button\n ref={(element) => {\n if (!element) rowRefs.delete(index());\n else rowRefs.set(index(), element);\n }}\n type=\"button\"\n id={optionId(index())}\n role=\"option\"\n aria-selected={activeIndex() === index()}\n data-active={activeIndex() === index() ? \"true\" : undefined}\n data-has-description={item().desc ? \"true\" : undefined}\n onMouseEnter={() => setActiveIndex(index())}\n onClick={() => execute(item())}\n >\n {/* Cloud keeps the preview box mounted once a row declares an image, so a\n failed load swaps in the fallback glyph instead of collapsing the row. */}\n <Show when={item().previewUrl?.startsWith(\"/\") || item().icon}>\n <span class=\"k2b-prompt-search__preview\">\n <Show\n when={item().previewUrl?.startsWith(\"/\") && !failedPreviews[index()]}\n fallback={<i class={item().icon ?? \"ti ti-file\"} aria-hidden=\"true\" />}\n >\n <img src={item().previewUrl} alt=\"\" onError={() => setFailedPreviews(index(), true)} />\n </Show>\n </span>\n </Show>\n <span class=\"k2b-prompt-search__copy\">\n <strong>{item().label}</strong>\n <Show when={item().desc}>{(description) => <small>{description()}</small>}</Show>\n </span>\n </button>\n )}\n </KeyedFor>\n </div>\n </Show>\n </div>\n </div>\n </div>\n </div>\n );\n },\n {\n panelClassName: \"k2b-dialog k2b-dialog--search is-bare\",\n contentClassName: \"k2b-dialog__viewport is-search\",\n initialFocus: \"first-input\",\n signal: options?.signal,\n cancelBehavior: options?.cancelBehavior,\n history: options?.history,\n ariaLabel: options?.ariaLabel ?? options?.title ?? resolveUiMessages().search,\n },\n );\n\nconst promptText = (content: string, defaultValue?: string, options?: DialogOptions) =>\n prompts\n .form({\n ...options,\n fields: {\n message: { type: \"info\", content: () => <div class=\"k2b-prompt-copy\">{content}</div> },\n value: {\n type: \"text\",\n label: false,\n default: defaultValue || \"\",\n },\n },\n })\n .then((result) => result?.value ?? null);\n\nconst promptNumber = (\n content: string,\n defaultValue?: number,\n options?: DialogOptions & {\n min?: number;\n max?: number;\n },\n) =>\n prompts\n .form({\n ...options,\n fields: {\n message: { type: \"info\", content: () => <div class=\"k2b-prompt-copy\">{content}</div> },\n value: {\n type: \"number\",\n label: false,\n default: defaultValue || 0,\n min: options?.min,\n max: options?.max,\n },\n },\n })\n .then((result) => result?.value ?? null);\n\n// The same object as `sharedPrompts`, which `PanelDialog` uses for its discard question: replacing `prompts.confirm`\n// (for example in a test) therefore reaches every confirmation.\nexport const prompts = Object.assign(sharedPrompts, {\n alert: (content: PromptContent, options?: DialogOptions): Promise<void | undefined> =>\n dialogCore.open<void>(\n (close) => (\n <div class=\"k2b-dialog__panel\">\n <DialogHeader\n title={options?.title || resolveUiMessages().info}\n icon={options?.icon}\n tone={promptTone(options?.variant)}\n close={() => close()}\n />\n <div class=\"k2b-dialog__body\">{content}</div>\n <footer class=\"k2b-dialog__actions\">\n <button type=\"button\" class=\"k2b-button\" data-variant={options?.variant ?? \"primary\"} onClick={() => close()}>\n {options?.confirmText || resolveUiMessages().ok}\n </button>\n </footer>\n </div>\n ),\n {\n panelClassName: panelClass(options),\n contentClassName: contentClass(options?.surface),\n signal: options?.signal,\n cancelBehavior: options?.cancelBehavior,\n history: options?.history,\n ariaLabel: options?.ariaLabel ?? options?.title ?? resolveUiMessages().info,\n },\n ),\n\n success: (content: PromptContent, options?: Omit<DialogOptions, \"variant\">): Promise<void | undefined> =>\n prompts.alert(content, {\n ...options,\n variant: \"success\",\n title: options?.title ?? resolveUiMessages().success,\n }),\n\n prompt: promptText,\n promptNumber,\n\n form: async <T extends Record<string, FieldSchema>>(config: PromptFormOptions<T>): Promise<InferFormValues<T> | null> =>\n (await dialogCore.open<InferFormValues<T> | null>((close) => <PromptFormDialog config={config} close={(value) => close(value)} />, {\n panelClassName: panelClass(config),\n contentClassName: contentClass(),\n signal: config.signal,\n cancelBehavior: config.cancelBehavior,\n ariaLabel: config.ariaLabel ?? config.title ?? resolvePromptMessages().form,\n })) ?? null,\n\n /**\n * Open custom content with a typed close callback and the dialog render context.\n * Register a dismiss handler to guard Escape, backdrop clicks and the supplied header's close button,\n * for example while saving. Explicit close(result) bypasses the guard. Without a handler, dismissal\n * keeps its existing behavior, including a header close button independent of cancelBehavior.\n */\n dialog: <T extends unknown = unknown>(component: DialogRender<T>, options?: DialogOptions): Promise<T | undefined> =>\n dialogCore.open<T>(\n (close, context) => {\n // A dismiss handler the component sets guards the header's close button as well as Escape and the backdrop.\n let dismiss = () => close(undefined);\n const body = component(close, {\n ...context,\n setDismissHandler: (handler) => {\n context.setDismissHandler(handler);\n dismiss = () => void context.requestDismiss();\n },\n });\n if (options?.surface === \"bare\" && options.header === false) return body;\n return (\n <div class=\"k2b-dialog__panel k2b-dialog__stack\">\n <Show when={options?.header !== false}>\n <DialogHeader title={options?.title} icon={options?.icon} tone={promptTone(options?.variant)} close={() => dismiss()} />\n </Show>\n <div class=\"k2b-dialog__content\">{body}</div>\n </div>\n );\n },\n {\n panelClassName: panelClass(options),\n contentClassName: contentClass(options?.surface),\n signal: options?.signal,\n cancelBehavior: options?.cancelBehavior,\n history: options?.history,\n ariaLabel: options?.ariaLabel ?? options?.title ?? resolveUiMessages().dialog,\n },\n ),\n\n search: openSearchPrompt,\n\n error: (content: string | HTMLElement, options?: DialogOptions) =>\n dialogCore.open(\n (close) => (\n <div class=\"k2b-dialog__panel\">\n <DialogHeader title={options?.title ?? resolveUiMessages().error} icon={options?.icon} tone=\"danger\" close={close} />\n <div class=\"k2b-dialog__body\">{content}</div>\n <footer class=\"k2b-dialog__actions\">\n <button type=\"button\" class=\"k2b-button\" onClick={() => close()}>\n {options?.confirmText || resolveUiMessages().close}\n </button>\n </footer>\n </div>\n ),\n {\n panelClassName: panelClass({ ...options, variant: \"danger\" }),\n contentClassName: contentClass(options?.surface),\n signal: options?.signal,\n cancelBehavior: options?.cancelBehavior,\n history: options?.history,\n ariaLabel: options?.ariaLabel ?? options?.title ?? resolveUiMessages().error,\n },\n ),\n});\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":[],"sources":["feedback/prompts.tsx"],"sourcesContent":["import { mutation, timed } from \"@k2b/stdlib/solid\";\nimport { createEffect, createMemo, createSignal, createUniqueId, For, type JSX, onCleanup, Show } from \"solid-js\";\nimport { createStore } from \"solid-js/store\";\nimport { Checkbox } from \"../inputs/Checkbox\";\nimport { PinInput } from \"../inputs/ChoiceInputs\";\nimport { DatePicker, DateTimePicker } from \"../inputs/DatePicker\";\nimport { ImageInput } from \"../inputs/FileInputs\";\nimport { NumberInput } from \"../inputs/NumberInput\";\nimport { Select } from \"../inputs/Select\";\nimport { resolveSelectMessages } from \"../inputs/select-messages\";\nimport { TagsInput } from \"../inputs/TagsInput\";\nimport { TextInput } from \"../inputs/TextInput\";\nimport { KeyedFor } from \"../internal/keyed-for\";\nimport { resolveUiMessages } from \"../intl/messages\";\nimport { type DialogRender, dialogCore, type OpenDialogOptions } from \"./dialog-core\";\nimport {\n contentClass,\n DialogHeader,\n type PromptContent,\n panelClass,\n promptButtonVariant,\n promptTone,\n sharedPrompts,\n} from \"./prompt-confirm\";\nimport { resolvePromptMessages } from \"./prompt-messages\";\n\nexport { DialogHeader } from \"./prompt-confirm\";\n\nexport interface DialogOptions {\n signal?: AbortSignal;\n title?: string;\n ariaLabel?: string;\n icon?: string;\n confirmText?: string;\n cancelText?: string | false;\n variant?: \"danger\" | \"primary\" | \"success\" | \"warning\";\n /** `full` fills the available viewport and becomes edge-to-edge on narrow screens. */\n size?: \"small\" | \"medium\" | \"large\" | \"wide\" | \"full\";\n surface?: \"default\" | \"bare\";\n header?: false;\n cancelBehavior?: OpenDialogOptions[\"cancelBehavior\"];\n /** Back closes the prompt like Cancel, as in a phone app; see `OpenDialogOptions.history`. */\n history?: boolean;\n}\n\nexport interface ConfirmOptions extends DialogOptions {\n confirmationPhrase?: string;\n}\n\nexport type PromptSearchItem<T = unknown> = {\n /**\n * Stable identity of the result, such as its record ID. With it, a newer answer that contains the same result keeps\n * its row, so a click in progress still lands. Without it, each answer replaces the rows.\n */\n id?: string;\n label: string;\n desc?: string;\n icon?: string;\n previewUrl?: string;\n value?: T;\n};\n\nexport type PromptSearchInput = {\n query: string;\n abortSignal: AbortSignal;\n};\n\nexport type PromptSearchOptions = DialogOptions & {\n placeholder?: string;\n icon?: string;\n initialQuery?: string;\n minQueryLength?: number;\n debounceMs?: number;\n emptyText?: string;\n noResultsText?: string;\n};\n\nexport type PromptFieldBase<T = any> = {\n label?: string | false;\n description?: string;\n placeholder?: string;\n required?: boolean;\n default?: T;\n validate?: (value: T | undefined) => string | null;\n};\n\nexport type FieldSchema =\n | (PromptFieldBase<string> & {\n type: \"text\";\n multiline?: boolean;\n lines?: number;\n maxLength?: number;\n minLength?: number;\n icon?: string;\n activeIcon?: string;\n password?: boolean;\n markdown?: boolean;\n })\n | (PromptFieldBase<number> & {\n type: \"number\";\n min?: number;\n max?: number;\n step?: number;\n })\n | (PromptFieldBase<string> & {\n type: \"image\";\n round?: boolean;\n ariaLabel?: string;\n accept?: string;\n })\n | (PromptFieldBase<string> & {\n type: \"pin\";\n length?: number;\n stretch?: boolean;\n })\n | (PromptFieldBase<string> & {\n type: \"select\";\n options: string[] | { id: string; label?: string; description?: string; icon?: string }[];\n icon?: string;\n activeIcon?: string;\n clearable?: boolean;\n })\n | (PromptFieldBase<string[]> & {\n type: \"tags\";\n maxTags?: number;\n minTags?: number;\n icon?: string;\n activeIcon?: string;\n })\n | (PromptFieldBase<boolean> & {\n type: \"boolean\";\n })\n | (PromptFieldBase<string> & {\n type: \"datetime\";\n dateOnly?: boolean;\n /** A date whose time is optional, as `DateTimePicker`'s `optionalTime`. */\n optionalTime?: boolean;\n })\n | {\n type: \"info\";\n content: string | JSX.Element | (() => JSX.Element);\n };\n\ntype InferFieldType<T extends FieldSchema> = T extends { type: \"text\" }\n ? string\n : T extends { type: \"number\" }\n ? number\n : T extends { type: \"image\" }\n ? string\n : T extends { type: \"pin\" }\n ? string\n : T extends { type: \"select\" }\n ? string\n : T extends { type: \"tags\" }\n ? string[]\n : T extends { type: \"boolean\" }\n ? boolean\n : T extends { type: \"datetime\" }\n ? string\n : T extends { type: \"currency\" }\n ? number\n : T extends { type: \"info\" }\n ? never\n : never;\n\ntype InferFormValues<T extends Record<string, FieldSchema>> = {\n [K in keyof T as T[K] extends { type: \"info\" } ? never : K]: T[K] extends { required: true }\n ? InferFieldType<T[K]>\n : InferFieldType<T[K]> | undefined;\n};\n\ntype PromptFormValue = string | number | boolean | string[] | undefined;\ntype PromptFormOptions<T extends Record<string, FieldSchema>> = {\n signal?: AbortSignal;\n title?: string;\n ariaLabel?: string;\n icon?: string;\n fields: T;\n confirmText?: string;\n cancelText?: string | false;\n variant?: \"danger\" | \"primary\" | \"success\" | \"warning\";\n size?: DialogOptions[\"size\"];\n cancelBehavior?: DialogOptions[\"cancelBehavior\"];\n};\n\nconst isEmpty = (value: unknown): boolean =>\n value === undefined || value === null || value === \"\" || (Array.isArray(value) && value.length === 0);\n\nexport const createFormState = <T extends Record<string, FieldSchema>>(schema: T) => {\n const messages = resolveUiMessages();\n const promptMessages = resolvePromptMessages();\n const [values, setValues] = createStore<Record<string, PromptFormValue>>({});\n const [errors, setErrors] = createStore<Record<string, string | undefined>>({});\n // Errors appear with the first submit and then follow every change. Before that, a check that fails mid-input,\n // such as a URL still being typed, would interrupt the user with an alert on the first character.\n let submitted = false;\n\n for (const [key, field] of Object.entries(schema)) {\n if (field.type !== \"info\" && \"default\" in field) setValues(key, field.default as PromptFormValue);\n }\n\n const validateField = (key: string, value: PromptFormValue): string | null => {\n const field = schema[key];\n if (!field || field.type === \"info\") return null;\n if (field.type === \"boolean\" && field.required && value !== true) return messages.required;\n if (field.required && isEmpty(value)) return messages.required;\n if (\"validate\" in field && field.validate) {\n const customError = (field.validate as (next: never) => string | null)(value as never);\n if (customError) return customError;\n }\n if (field.type === \"text\" && typeof value === \"string\" && value.length > 0) {\n if (field.minLength !== undefined && value.length < field.minLength) return promptMessages.minCharacters({ count: field.minLength });\n if (field.maxLength !== undefined && value.length > field.maxLength) return promptMessages.maxCharacters({ count: field.maxLength });\n }\n if (field.type === \"tags\" && Array.isArray(value) && value.length > 0) {\n if (field.minTags !== undefined && value.length < field.minTags) return promptMessages.minTags({ count: field.minTags });\n if (field.maxTags !== undefined && value.length > field.maxTags) return promptMessages.maxTags({ count: field.maxTags });\n }\n return null;\n };\n\n const updateField = (key: string, value: PromptFormValue) => {\n setValues(key, value);\n if (submitted) setErrors(key, validateField(key, value) ?? undefined);\n };\n\n const validateAll = (): boolean => {\n submitted = true;\n let valid = true;\n for (const [key, field] of Object.entries(schema)) {\n if (field.type === \"info\") continue;\n const error = validateField(key, values[key]);\n setErrors(key, error ?? undefined);\n if (error) valid = false;\n }\n return valid;\n };\n\n const reset = () => {\n submitted = false;\n for (const [key, field] of Object.entries(schema)) {\n if (field.type === \"info\") continue;\n setValues(key, \"default\" in field ? (field.default as PromptFormValue) : undefined);\n setErrors(key, undefined);\n }\n };\n\n return { values, errors, updateField, validateAll, reset };\n};\n\nconst renderInfo = (content: Extract<FieldSchema, { type: \"info\" }>[\"content\"]): JSX.Element => {\n if (typeof content === \"string\") return <p>{content}</p>;\n if (typeof content === \"function\") return content();\n return content;\n};\n\nconst PromptControl = (props: {\n field: Exclude<FieldSchema, { type: \"info\" }>;\n value: () => PromptFormValue;\n update: (value: PromptFormValue) => void;\n error: () => string | undefined;\n submit: () => void;\n}): JSX.Element => {\n const label = props.field.label || undefined;\n\n switch (props.field.type) {\n case \"text\":\n return (\n <TextInput\n label={label}\n description={props.field.description}\n required={props.field.required}\n placeholder={props.field.placeholder}\n error={props.error}\n value={String(props.value() ?? \"\")}\n onValueChange={(value) => props.update(value ?? undefined)}\n onSubmit={props.submit}\n multiline={props.field.multiline}\n lines={props.field.lines}\n icon={props.field.icon}\n activeIcon={props.field.activeIcon}\n password={props.field.password}\n markdown={props.field.markdown}\n minLength={props.field.minLength}\n maxLength={props.field.maxLength}\n />\n );\n case \"number\":\n return (\n <NumberInput\n label={label}\n description={props.field.description}\n required={props.field.required}\n placeholder={props.field.placeholder}\n error={props.error}\n value={typeof props.value() === \"number\" ? (props.value() as number) : null}\n onValueChange={(value) => props.update(value ?? undefined)}\n min={props.field.min}\n max={props.field.max}\n step={props.field.step}\n />\n );\n case \"image\":\n return (\n <ImageInput\n label={label}\n description={props.field.description}\n required={props.field.required}\n error={props.error}\n value={() => (typeof props.value() === \"string\" ? (props.value() as string) : null)}\n onValueChange={(value) => props.update(value ?? undefined)}\n round={props.field.round}\n aria-label={props.field.ariaLabel}\n accept={props.field.accept}\n />\n );\n case \"pin\":\n return (\n <PinInput\n label={label}\n description={props.field.description}\n required={props.field.required}\n error={props.error}\n value={() => String(props.value() ?? \"\")}\n onValueChange={props.update}\n length={props.field.length}\n stretch={props.field.stretch}\n />\n );\n case \"select\":\n return (\n <Select\n label={label}\n description={props.field.description}\n required={props.field.required}\n placeholder={props.field.placeholder}\n error={props.error}\n value={() => (typeof props.value() === \"string\" ? (props.value() as string) : null)}\n onValueChange={(value) => props.update(value ?? undefined)}\n options={props.field.options}\n icon={props.field.icon}\n activeIcon={props.field.activeIcon}\n clearable={props.field.clearable}\n />\n );\n case \"tags\":\n return (\n <TagsInput\n label={label}\n description={props.field.description}\n required={props.field.required}\n placeholder={props.field.placeholder}\n error={props.error}\n value={() => (Array.isArray(props.value()) ? (props.value() as string[]) : [])}\n onValueChange={props.update}\n maxTags={props.field.maxTags}\n icon={props.field.icon}\n activeIcon={props.field.activeIcon}\n />\n );\n case \"boolean\":\n return (\n <Checkbox\n label={label}\n description={props.field.description}\n required={props.field.required}\n error={props.error}\n value={() => Boolean(props.value())}\n onValueChange={props.update}\n />\n );\n case \"datetime\": {\n const pickerProps = {\n label,\n description: props.field.description,\n required: props.field.required,\n placeholder: props.field.placeholder,\n error: props.error,\n value: () => (typeof props.value() === \"string\" ? (props.value() as string) : null),\n onValueChange: (value: string | null) => props.update(value ?? \"\"),\n clearable: true,\n };\n return props.field.dateOnly ? (\n <DatePicker {...pickerProps} />\n ) : (\n <DateTimePicker {...pickerProps} optionalTime={props.field.optionalTime} />\n );\n }\n }\n};\n\nconst PromptFormDialog = <T extends Record<string, FieldSchema>>(props: {\n config: PromptFormOptions<T>;\n close: (value: InferFormValues<T> | null) => void;\n}): JSX.Element => {\n const state = createFormState(props.config.fields);\n const submit = () => {\n if (state.validateAll()) props.close(state.values as InferFormValues<T>);\n };\n const handleSubmit = (event: SubmitEvent) => {\n event.preventDefault();\n submit();\n };\n\n return (\n <form class=\"k2b-dialog__panel\" onSubmit={handleSubmit}>\n <DialogHeader\n title={props.config.title}\n icon={props.config.icon}\n tone={promptTone(props.config.variant)}\n close={() => props.close(null)}\n />\n <div class=\"k2b-dialog__body k2b-prompt-form\">\n <For each={Object.entries(props.config.fields)}>\n {([key, field]) => {\n if (field.type === \"info\") return <div class=\"k2b-prompt-form__info\">{renderInfo(field.content)}</div>;\n return (\n <PromptControl\n field={field}\n value={() => state.values[key]}\n update={(value) => state.updateField(key, value)}\n error={() => state.errors[key]}\n submit={submit}\n />\n );\n }}\n </For>\n </div>\n <footer class=\"k2b-dialog__actions\">\n <Show when={props.config.cancelText !== false}>\n <button type=\"button\" class=\"k2b-button\" data-variant=\"secondary\" onClick={() => props.close(null)}>\n {props.config.cancelText || resolveUiMessages().cancel}\n </button>\n </Show>\n <button type=\"submit\" class=\"k2b-button\" data-variant={promptButtonVariant(props.config.variant)}>\n {props.config.confirmText ?? resolveUiMessages().save}\n </button>\n </footer>\n </form>\n );\n};\n\n// Results without an ID keep today's behavior: each object is its own identity, so a new answer replaces the row.\nconst anonymousRows = new WeakMap<object, string>();\nlet anonymousRow = 0;\nconst searchRowIdentity = (item: PromptSearchItem<unknown>): string => {\n if (item.id !== undefined) return `id:${item.id}`;\n const known = anonymousRows.get(item);\n if (known !== undefined) return known;\n const key = `object:${anonymousRow++}`;\n anonymousRows.set(item, key);\n return key;\n};\n\ntype CloudSearchResolver<T> = (input: PromptSearchInput) => Promise<PromptSearchItem<T>[]> | PromptSearchItem<T>[];\n\nconst openSearchPrompt = <T extends unknown = unknown>(resolver: CloudSearchResolver<T>, options?: PromptSearchOptions) =>\n dialogCore.open<PromptSearchItem<T>>(\n (close) => {\n const [query, setQuery] = createSignal(options?.initialQuery ?? \"\");\n const [items, setItems] = createSignal<PromptSearchItem<T>[]>([]);\n const [activeIndex, setActiveIndex] = createSignal(0);\n const [hasLoaded, setHasLoaded] = createSignal(false);\n const [failedPreviews, setFailedPreviews] = createStore<Record<number, true>>({});\n const [activeSearchQuery, setActiveSearchQuery] = createSignal(\"\");\n const rowRefs = new Map<number, HTMLButtonElement>();\n const searchId = `k2b-prompt-search-${createUniqueId()}`;\n const listboxId = `${searchId}-listbox`;\n const optionId = (index: number) => `${searchId}-option-${index}`;\n\n const minQueryLength = options?.minQueryLength ?? 0;\n const debounceMs = options?.debounceMs ?? 180;\n const searchMutation = mutation.create<{ query: string; items: PromptSearchItem<T>[] }, string, { requestQuery: string }>({\n onBefore: (requestQuery) => ({ requestQuery }),\n mutation: async (requestQuery, context) => {\n const result = await resolver({\n query: requestQuery,\n abortSignal: context.abortSignal,\n });\n return { query: requestQuery, items: (result ?? []).slice() };\n },\n onSuccess: (result, context) => {\n if (!context || context.requestQuery !== activeSearchQuery()) return;\n setItems(result.items);\n setActiveIndex(0);\n setHasLoaded(true);\n },\n onError: (error, context) => {\n if (!context || context.requestQuery !== activeSearchQuery() || error.name === \"AbortError\") return;\n setItems([]);\n setActiveIndex(0);\n setHasLoaded(true);\n },\n });\n const searchError = createMemo(() => {\n const error = searchMutation.error();\n if (!error || error.name === \"AbortError\") return null;\n return error.message || resolvePromptMessages().searchFailed;\n });\n const shouldShowResults = createMemo(() => {\n if (query().trim().length < minQueryLength) return false;\n return hasLoaded() || searchError() !== null || items().length > 0;\n });\n const emptyStateText = createMemo(() => {\n if (!hasLoaded()) return options?.emptyText ?? resolveSelectMessages().typeToSearch;\n return options?.noResultsText ?? resolveUiMessages().noResults;\n });\n const { debouncedFn: debounceSearch, cancel: cancelDebounce } = timed.debounce((nextQuery: string) => {\n setActiveSearchQuery(nextQuery);\n searchMutation.abort();\n void searchMutation.mutate(nextQuery);\n }, debounceMs);\n\n const execute = (item?: PromptSearchItem<T>) => {\n if (!item) return;\n close(item);\n };\n const moveSelection = (delta: -1 | 1) => {\n const list = items();\n if (list.length === 0) return;\n setActiveIndex((activeIndex() + delta + list.length) % list.length);\n };\n\n createEffect(() => {\n const list = items();\n const maxIndex = list.length - 1;\n if (maxIndex < 0) {\n setActiveIndex(0);\n return;\n }\n if (activeIndex() > maxIndex) setActiveIndex(maxIndex);\n rowRefs.get(activeIndex())?.scrollIntoView({ block: \"nearest\" });\n });\n createEffect(() => {\n const nextQuery = query().trim();\n setFailedPreviews({});\n if (nextQuery.length < minQueryLength) {\n cancelDebounce();\n searchMutation.abort();\n setItems([]);\n setActiveIndex(0);\n setHasLoaded(false);\n setActiveSearchQuery(\"\");\n return;\n }\n debounceSearch(nextQuery);\n });\n onCleanup(() => {\n cancelDebounce();\n searchMutation.abort();\n });\n\n return (\n <div class=\"k2b-prompt-search-shell\">\n <Show when={options?.title}>{(title) => <p class=\"k2b-prompt-search-shell__title\">{title()}</p>}</Show>\n <div class=\"k2b-prompt-search\">\n <label class=\"k2b-prompt-search__input\">\n <i class={options?.icon ?? \"ti ti-search\"} aria-hidden=\"true\" />\n <input\n id={searchId}\n type=\"search\"\n role=\"combobox\"\n aria-label={options?.ariaLabel ?? options?.title ?? resolveUiMessages().search}\n aria-autocomplete=\"list\"\n aria-controls={listboxId}\n aria-expanded={shouldShowResults()}\n aria-activedescendant={shouldShowResults() && items().length > 0 ? optionId(activeIndex()) : undefined}\n aria-busy={searchMutation.loading()}\n value={query()}\n onInput={(event) => setQuery(event.currentTarget.value)}\n onKeyDown={(event) => {\n if (event.key === \"ArrowDown\") {\n event.preventDefault();\n moveSelection(1);\n } else if (event.key === \"ArrowUp\") {\n event.preventDefault();\n moveSelection(-1);\n } else if (event.key === \"Enter\") {\n event.preventDefault();\n execute(items()[activeIndex()]);\n }\n }}\n placeholder={options?.placeholder ?? resolveUiMessages().search}\n spellcheck={false}\n autocapitalize=\"off\"\n autocomplete=\"off\"\n autocorrect=\"off\"\n />\n <Show when={searchMutation.loading()}>\n <i class=\"ti ti-loader-2 k2b-spin\" aria-hidden=\"true\" />\n </Show>\n </label>\n <div\n class=\"k2b-prompt-search__collapse\"\n style={{\n height: shouldShowResults() ? \"var(--k2b-search-body-max)\" : \"0px\",\n opacity: shouldShowResults() ? \"1\" : \"0\",\n }}\n >\n <div class=\"k2b-prompt-search__results\" onWheel={(event) => event.stopPropagation()}>\n <Show when={searchError()}>\n {(message) => (\n <div class=\"k2b-prompt-search__error\" role=\"status\" aria-live=\"polite\">\n {message()}\n </div>\n )}\n </Show>\n <Show\n when={items().length > 0}\n fallback={\n <p role=\"status\" aria-live=\"polite\">\n {emptyStateText()}\n </p>\n }\n >\n <div id={listboxId} class=\"k2b-prompt-search__list\" role=\"listbox\" aria-label={resolveUiMessages().searchResults}>\n <KeyedFor each={items()} by={searchRowIdentity}>\n {(item, index) => (\n <button\n ref={(element) => {\n if (!element) rowRefs.delete(index());\n else rowRefs.set(index(), element);\n }}\n type=\"button\"\n id={optionId(index())}\n role=\"option\"\n aria-selected={activeIndex() === index()}\n data-active={activeIndex() === index() ? \"true\" : undefined}\n data-has-description={item().desc ? \"true\" : undefined}\n onMouseEnter={() => setActiveIndex(index())}\n onClick={() => execute(item())}\n >\n {/* Cloud keeps the preview box mounted once a row declares an image, so a\n failed load swaps in the fallback glyph instead of collapsing the row. */}\n <Show when={item().previewUrl?.startsWith(\"/\") || item().icon}>\n <span class=\"k2b-prompt-search__preview\">\n <Show\n when={item().previewUrl?.startsWith(\"/\") && !failedPreviews[index()]}\n fallback={<i class={item().icon ?? \"ti ti-file\"} aria-hidden=\"true\" />}\n >\n <img src={item().previewUrl} alt=\"\" onError={() => setFailedPreviews(index(), true)} />\n </Show>\n </span>\n </Show>\n <span class=\"k2b-prompt-search__copy\">\n <strong>{item().label}</strong>\n <Show when={item().desc}>{(description) => <small>{description()}</small>}</Show>\n </span>\n </button>\n )}\n </KeyedFor>\n </div>\n </Show>\n </div>\n </div>\n </div>\n </div>\n );\n },\n {\n panelClassName: \"k2b-dialog k2b-dialog--search is-bare\",\n contentClassName: \"k2b-dialog__viewport is-search\",\n initialFocus: \"first-input\",\n signal: options?.signal,\n cancelBehavior: options?.cancelBehavior,\n history: options?.history,\n ariaLabel: options?.ariaLabel ?? options?.title ?? resolveUiMessages().search,\n },\n );\n\nconst promptText = (content: string, defaultValue?: string, options?: DialogOptions) =>\n prompts\n .form({\n ...options,\n fields: {\n message: { type: \"info\", content: () => <div class=\"k2b-prompt-copy\">{content}</div> },\n value: {\n type: \"text\",\n label: false,\n default: defaultValue || \"\",\n },\n },\n })\n .then((result) => result?.value ?? null);\n\nconst promptNumber = (\n content: string,\n defaultValue?: number,\n options?: DialogOptions & {\n min?: number;\n max?: number;\n },\n) =>\n prompts\n .form({\n ...options,\n fields: {\n message: { type: \"info\", content: () => <div class=\"k2b-prompt-copy\">{content}</div> },\n value: {\n type: \"number\",\n label: false,\n default: defaultValue || 0,\n min: options?.min,\n max: options?.max,\n },\n },\n })\n .then((result) => result?.value ?? null);\n\n// The same object as `sharedPrompts`, which `PanelDialog` uses for its discard question: replacing `prompts.confirm`\n// (for example in a test) therefore reaches every confirmation.\nexport const prompts = Object.assign(sharedPrompts, {\n alert: (content: PromptContent, options?: DialogOptions): Promise<void | undefined> =>\n dialogCore.open<void>(\n (close) => (\n <div class=\"k2b-dialog__panel\">\n <DialogHeader\n title={options?.title || resolveUiMessages().info}\n icon={options?.icon}\n tone={promptTone(options?.variant)}\n close={() => close()}\n />\n <div class=\"k2b-dialog__body\">{content}</div>\n <footer class=\"k2b-dialog__actions\">\n <button type=\"button\" class=\"k2b-button\" data-variant={promptButtonVariant(options?.variant)} onClick={() => close()}>\n {options?.confirmText || resolveUiMessages().ok}\n </button>\n </footer>\n </div>\n ),\n {\n panelClassName: panelClass(options),\n contentClassName: contentClass(options?.surface),\n signal: options?.signal,\n cancelBehavior: options?.cancelBehavior,\n history: options?.history,\n ariaLabel: options?.ariaLabel ?? options?.title ?? resolveUiMessages().info,\n },\n ),\n\n success: (content: PromptContent, options?: Omit<DialogOptions, \"variant\">): Promise<void | undefined> =>\n prompts.alert(content, {\n ...options,\n variant: \"success\",\n title: options?.title ?? resolveUiMessages().success,\n }),\n\n prompt: promptText,\n promptNumber,\n\n form: async <T extends Record<string, FieldSchema>>(config: PromptFormOptions<T>): Promise<InferFormValues<T> | null> =>\n (await dialogCore.open<InferFormValues<T> | null>((close) => <PromptFormDialog config={config} close={(value) => close(value)} />, {\n panelClassName: panelClass(config),\n contentClassName: contentClass(),\n signal: config.signal,\n cancelBehavior: config.cancelBehavior,\n ariaLabel: config.ariaLabel ?? config.title ?? resolvePromptMessages().form,\n })) ?? null,\n\n /**\n * Open custom content with a typed close callback and the dialog render context.\n * Register a dismiss handler to guard Escape, backdrop clicks and the supplied header's close button,\n * for example while saving. Explicit close(result) bypasses the guard. Without a handler, dismissal\n * keeps its existing behavior, including a header close button independent of cancelBehavior.\n */\n dialog: <T extends unknown = unknown>(component: DialogRender<T>, options?: DialogOptions): Promise<T | undefined> =>\n dialogCore.open<T>(\n (close, context) => {\n // A dismiss handler the component sets guards the header's close button as well as Escape and the backdrop.\n let dismiss = () => close(undefined);\n const body = component(close, {\n ...context,\n setDismissHandler: (handler) => {\n context.setDismissHandler(handler);\n dismiss = () => void context.requestDismiss();\n },\n });\n if (options?.surface === \"bare\" && options.header === false) return body;\n return (\n <div class=\"k2b-dialog__panel k2b-dialog__stack\">\n <Show when={options?.header !== false}>\n <DialogHeader title={options?.title} icon={options?.icon} tone={promptTone(options?.variant)} close={() => dismiss()} />\n </Show>\n <div class=\"k2b-dialog__content\">{body}</div>\n </div>\n );\n },\n {\n panelClassName: panelClass(options),\n contentClassName: contentClass(options?.surface),\n signal: options?.signal,\n cancelBehavior: options?.cancelBehavior,\n history: options?.history,\n ariaLabel: options?.ariaLabel ?? options?.title ?? resolveUiMessages().dialog,\n },\n ),\n\n search: openSearchPrompt,\n\n error: (content: string | HTMLElement, options?: DialogOptions) =>\n dialogCore.open(\n (close) => (\n <div class=\"k2b-dialog__panel\">\n <DialogHeader title={options?.title ?? resolveUiMessages().error} icon={options?.icon} tone=\"danger\" close={close} />\n <div class=\"k2b-dialog__body\">{content}</div>\n <footer class=\"k2b-dialog__actions\">\n <button type=\"button\" class=\"k2b-button\" onClick={() => close()}>\n {options?.confirmText || resolveUiMessages().close}\n </button>\n </footer>\n </div>\n ),\n {\n panelClassName: panelClass({ ...options, variant: \"danger\" }),\n contentClassName: contentClass(options?.surface),\n signal: options?.signal,\n cancelBehavior: options?.cancelBehavior,\n history: options?.history,\n ariaLabel: options?.ariaLabel ?? options?.title ?? resolveUiMessages().error,\n },\n ),\n});\n"],"mappings":"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","ignoreList":[]}
@@ -36,16 +36,26 @@ export function NumberInput(props) {
36
36
  const messages = useUiMessages();
37
37
  const inputMessages = useInputMessages();
38
38
  const separator = createMemo(() => decimalSeparator(local.locale ?? contextLocale()));
39
- // The visible text keeps the canonical number, only the decimal separator
40
- // follows the effective locale; grouping is never rendered while editing.
41
- const display = value => value == null ? "" : String(value).replace(".", separator());
42
- const [raw, setRaw] = createSignal(display(value()));
43
39
  const min = () => local.min ?? -Infinity;
44
40
  const max = () => local.max ?? Infinity;
45
41
  const step = () => local.step ?? 1;
46
42
  // `step` and the accepted decimals never disagree: a fractional step implies
47
43
  // its own precision unless the caller states `decimalPlaces` explicitly.
48
44
  const places = () => Math.max(0, local.decimalPlaces ?? fractionDigits(step()));
45
+ // Keep ASCII digits and no grouping so display text round-trips through parse,
46
+ // including numbers that String/toFixed would write in exponential notation.
47
+ const formatter = createMemo(() => new Intl.NumberFormat("en", {
48
+ useGrouping: false,
49
+ minimumFractionDigits: places(),
50
+ maximumFractionDigits: places()
51
+ }));
52
+ const display = value => {
53
+ if (value == null) return "";
54
+ // Match normalize's rounding; toFixed switches to exponents at 1e21.
55
+ const text = Math.abs(value) < 1e21 ? value.toFixed(places()) : formatter().format(value);
56
+ return text.replace(".", separator());
57
+ };
58
+ const [raw, setRaw] = createSignal(display(value()));
49
59
  const filter = input => {
50
60
  let output = "";
51
61
  let decimal = false;
@@ -89,7 +99,9 @@ export function NumberInput(props) {
89
99
  };
90
100
  createEffect(() => {
91
101
  if (focused()) return;
92
- if (parse(raw()) !== value()) setRaw(display(value()));
102
+ // Synchronize display text: precision or locale can change
103
+ // without changing the controlled number. This effect never emits changes.
104
+ setRaw(display(value()));
93
105
  });
94
106
  // Enter already committed the current text, so leaving the field does not commit it twice.
95
107
  let committedOnEnter = false;