@svadmin/ui 0.69.1 → 0.72.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 (158) hide show
  1. package/dist/actions.js +1 -1
  2. package/dist/app.css +102 -63
  3. package/dist/app.theme.css +102 -63
  4. package/dist/component-registry.svelte.d.ts +33 -19
  5. package/dist/component-registry.svelte.js +6 -4
  6. package/dist/components/AdminApp.svelte +55 -53
  7. package/dist/components/AdminApp.svelte.d.ts +2 -2
  8. package/dist/components/ApiSettings.svelte +19 -1
  9. package/dist/components/AuditLogDrawer.svelte +14 -3
  10. package/dist/components/AutoForm.svelte +146 -48
  11. package/dist/components/AutoForm.svelte.d.ts +2 -0
  12. package/dist/components/AutoTable.svelte +358 -258
  13. package/dist/components/AutoTable.svelte.d.ts +1 -0
  14. package/dist/components/BoundRecordDetailDrawer.svelte +166 -0
  15. package/dist/components/BoundRecordDetailDrawer.svelte.d.ts +9 -0
  16. package/dist/components/Breadcrumbs.svelte +7 -4
  17. package/dist/components/CancelTaskButton.svelte +9 -5
  18. package/dist/components/ColumnHeaderFilter.svelte +4 -3
  19. package/dist/components/ColumnSettings.svelte +1 -0
  20. package/dist/components/ComboboxField.svelte +90 -30
  21. package/dist/components/ComboboxField.svelte.d.ts +2 -2
  22. package/dist/components/CreatePage.svelte +3 -1
  23. package/dist/components/DetailDrawer.svelte +4 -0
  24. package/dist/components/DetailDrawer.svelte.d.ts +1 -0
  25. package/dist/components/DevTools.svelte +1 -1
  26. package/dist/components/DraggableGrid.svelte +1 -0
  27. package/dist/components/DraggableHeader.svelte +5 -9
  28. package/dist/components/DraggableHeader.svelte.d.ts +43 -18
  29. package/dist/components/DraggableRowTable.svelte +2 -2
  30. package/dist/components/DynamicFormList.svelte +17 -17
  31. package/dist/components/DynamicFormList.svelte.d.ts +2 -1
  32. package/dist/components/EditPage.svelte +3 -1
  33. package/dist/components/EditableTable.svelte +4 -0
  34. package/dist/components/ErrorPage.svelte +3 -1
  35. package/dist/components/FieldDisplay.svelte +14 -0
  36. package/dist/components/FieldDisplay.svelte.d.ts +7 -0
  37. package/dist/components/FieldRenderer.svelte +9 -5
  38. package/dist/components/FilterBuilder.svelte +19 -8
  39. package/dist/components/FilterDropdown.svelte.d.ts +1 -1
  40. package/dist/components/Header.svelte +5 -6
  41. package/dist/components/ImportWizard.svelte +3 -2
  42. package/dist/components/InfiniteList.svelte +22 -8
  43. package/dist/components/InfiniteList.svelte.d.ts +5 -3
  44. package/dist/components/InlineEdit.svelte +114 -44
  45. package/dist/components/JsonSchemaForm.svelte +19 -14
  46. package/dist/components/Layout.svelte +19 -15
  47. package/dist/components/LazyTaskQueueDrawer.svelte +26 -0
  48. package/dist/components/LazyTaskQueueDrawer.svelte.d.ts +8 -0
  49. package/dist/components/ListPage.svelte +7 -6
  50. package/dist/components/MasterDetailView.svelte +3 -3
  51. package/dist/components/MediaLibraryModal.svelte +5 -2
  52. package/dist/components/MentionsInput.svelte +4 -3
  53. package/dist/components/NavigateToResource.svelte +3 -2
  54. package/dist/components/PermissionMatrix.svelte +4 -3
  55. package/dist/components/ProfilePage.svelte +2 -2
  56. package/dist/components/QuickEditDrawer.svelte +39 -0
  57. package/dist/components/QuickEditDrawer.svelte.d.ts +8 -0
  58. package/dist/components/RecordDetailDrawer.svelte +14 -108
  59. package/dist/components/RecordRowActions.svelte +41 -0
  60. package/dist/components/RecordRowActions.svelte.d.ts +14 -0
  61. package/dist/components/ResourceAccessGuard.svelte +7 -5
  62. package/dist/components/RetryTaskButton.svelte +9 -5
  63. package/dist/components/RowActions.svelte +5 -3
  64. package/dist/components/SensitiveDataMask.svelte +3 -3
  65. package/dist/components/SettingsPage.svelte +1 -1
  66. package/dist/components/ShowPage.svelte +44 -38
  67. package/dist/components/Sidebar.svelte +10 -8
  68. package/dist/components/SplitPaneLayout.svelte +4 -2
  69. package/dist/components/StepsForm.svelte +161 -44
  70. package/dist/components/StepsForm.svelte.d.ts +1 -0
  71. package/dist/components/TaskDetails.svelte +20 -7
  72. package/dist/components/TaskList.svelte +19 -7
  73. package/dist/components/TaskQueueDrawer.svelte +21 -22
  74. package/dist/components/Toast.svelte +4 -2
  75. package/dist/components/TooltipButton.svelte +1 -1
  76. package/dist/components/TreeSelect.svelte +4 -2
  77. package/dist/components/ValidatedField.svelte +27 -0
  78. package/dist/components/ValidatedField.svelte.d.ts +35 -0
  79. package/dist/components/account/ImportMembersPage.svelte +2 -2
  80. package/dist/components/account/SecurityLogPage.svelte +3 -1
  81. package/dist/components/account/SettingsEnterprisePage.svelte +7 -5
  82. package/dist/components/account/TeamMembersPage.svelte +1 -1
  83. package/dist/components/buttons/CloneButton.svelte +6 -4
  84. package/dist/components/buttons/DeleteButton.svelte +95 -29
  85. package/dist/components/buttons/DeleteButton.svelte.d.ts +2 -0
  86. package/dist/components/buttons/EditButton.svelte +6 -4
  87. package/dist/components/buttons/ExportButton.svelte +22 -4
  88. package/dist/components/buttons/ImportButton.svelte +83 -38
  89. package/dist/components/buttons/ImportButton.svelte.d.ts +6 -10
  90. package/dist/components/buttons/RefreshButton.svelte +48 -8
  91. package/dist/components/buttons/ShowButton.svelte +6 -4
  92. package/dist/components/content/ApiKeyList.svelte +3 -1
  93. package/dist/components/content/ContentPageShell.svelte +3 -1
  94. package/dist/components/content/FileList.svelte +3 -1
  95. package/dist/components/content/MemberList.svelte +3 -1
  96. package/dist/components/content/NetworkTable.svelte +3 -1
  97. package/dist/components/content/SecurityEventTable.svelte +3 -1
  98. package/dist/components/content/StatusTabs.svelte +2 -2
  99. package/dist/components/fieldComponentMap.d.ts +18 -13
  100. package/dist/components/fieldComponentMap.js +95 -47
  101. package/dist/components/fields/AvatarField.svelte +1 -1
  102. package/dist/components/fields/ChoiceField.svelte +16 -0
  103. package/dist/components/fields/ChoiceField.svelte.d.ts +10 -0
  104. package/dist/components/fields/CodeField.svelte +11 -12
  105. package/dist/components/fields/CodeField.svelte.d.ts +1 -1
  106. package/dist/components/fields/DateRangeField.svelte +2 -4
  107. package/dist/components/fields/ImageField.svelte +3 -1
  108. package/dist/components/fields/ImagesField.svelte +23 -0
  109. package/dist/components/fields/ImagesField.svelte.d.ts +6 -0
  110. package/dist/components/fields/JsonField.svelte +19 -13
  111. package/dist/components/fields/PasswordField.svelte +5 -0
  112. package/dist/components/fields/PasswordField.svelte.d.ts +6 -0
  113. package/dist/components/fields/json-value.d.ts +11 -0
  114. package/dist/components/fields/json-value.js +28 -0
  115. package/dist/components/profile/ActivityTimeline.svelte +2 -2
  116. package/dist/components/record-detail.svelte.d.ts +16 -0
  117. package/dist/components/record-detail.svelte.js +28 -0
  118. package/dist/components/saved-list-views.js +29 -29
  119. package/dist/components/table-contract.d.ts +13 -0
  120. package/dist/components/table-contract.js +42 -0
  121. package/dist/components/task-utils.js +4 -2
  122. package/dist/components/ui/alert/alert-variants.d.ts +2 -3
  123. package/dist/components/ui/alert/alert-variants.js +1 -2
  124. package/dist/components/ui/alert/alert.svelte +4 -5
  125. package/dist/components/ui/alert/alert.svelte.d.ts +3 -8
  126. package/dist/components/ui/alert/index.js +0 -2
  127. package/dist/components/ui/avatar/avatar-variants.d.ts +2 -3
  128. package/dist/components/ui/avatar/avatar-variants.js +1 -2
  129. package/dist/components/ui/avatar/avatar.svelte +5 -6
  130. package/dist/components/ui/avatar/avatar.svelte.d.ts +3 -8
  131. package/dist/components/ui/badge/badge-variants.d.ts +2 -3
  132. package/dist/components/ui/badge/badge-variants.js +1 -2
  133. package/dist/components/ui/badge/badge.svelte +4 -5
  134. package/dist/components/ui/badge/badge.svelte.d.ts +3 -8
  135. package/dist/components/ui/badge/index.js +0 -2
  136. package/dist/components/ui/button/button-variants.d.ts +2 -3
  137. package/dist/components/ui/button/button-variants.js +1 -2
  138. package/dist/components/ui/button/button.svelte +100 -44
  139. package/dist/components/ui/button/button.svelte.d.ts +8 -12
  140. package/dist/components/ui/button/index.js +0 -2
  141. package/dist/components/ui/command/command-dialog.svelte +3 -1
  142. package/dist/components/ui/command/command-dialog.svelte.d.ts +1 -1
  143. package/dist/components/ui/command/command-group.svelte +4 -2
  144. package/dist/components/ui/command/command-item.svelte +4 -2
  145. package/dist/components/ui/command/command-separator.svelte +3 -1
  146. package/dist/components/ui/command/index.d.ts +5 -5
  147. package/dist/components/ui/input/input.svelte +40 -20
  148. package/dist/components/ui/input/input.svelte.d.ts +5 -4
  149. package/dist/components/ui/sheet/sheet.svelte +9 -3
  150. package/dist/components/ui/sheet/sheet.svelte.d.ts +1 -0
  151. package/dist/components/ui/tooltip/tooltip.svelte +4 -2
  152. package/dist/index.d.ts +1 -1
  153. package/dist/inline-value.d.ts +5 -0
  154. package/dist/inline-value.js +24 -0
  155. package/dist/numeric-input.d.ts +2 -0
  156. package/dist/numeric-input.js +9 -0
  157. package/dist/types.d.ts +3 -3
  158. package/package.json +11 -5
@@ -2,24 +2,29 @@
2
2
  import { cn, type WithElementRef } from "../../../utils.js";
3
3
  import type { HTMLAnchorAttributes, HTMLButtonAttributes } from "svelte/elements";
4
4
  import {
5
- buttonVariants as variants,
6
- type ButtonSize as Size,
7
- type ButtonVariant as Variant,
5
+ buttonVariants as resolveButtonVariants,
6
+ type ButtonSize as ButtonSizeValue,
7
+ type ButtonVariant as ButtonVariantValue,
8
8
  } from "./button-variants.js";
9
9
 
10
- export const buttonVariants = variants;
11
- export type ButtonSize = Size;
12
- export type ButtonVariant = Variant;
10
+ export { buttonVariants, type ButtonSize, type ButtonVariant } from "./button-variants.js";
13
11
 
14
- export type ButtonProps = WithElementRef<HTMLButtonAttributes, HTMLButtonElement> &
15
- WithElementRef<HTMLAnchorAttributes, HTMLAnchorElement> & {
16
- variant?: ButtonVariant;
17
- size?: ButtonSize;
12
+ export type ButtonProps = WithElementRef<
13
+ HTMLButtonAttributes & HTMLAnchorAttributes,
14
+ HTMLButtonElement | HTMLAnchorElement
15
+ > & {
16
+ variant?: ButtonVariantValue;
17
+ size?: ButtonSizeValue;
18
+ disabledReason?: string;
19
+ restrictionClass?: string;
20
+ restrictionStyle?: string;
18
21
  };
19
22
  </script>
20
23
 
21
24
  <script lang="ts">
22
- /* eslint-disable no-useless-assignment, @typescript-eslint/no-explicit-any */
25
+ import * as Tooltip from "../tooltip/index.js";
26
+
27
+ const uid = $props.id();
23
28
  let {
24
29
  class: className,
25
30
  variant = "default",
@@ -28,45 +33,96 @@
28
33
  href = undefined,
29
34
  type = "button",
30
35
  disabled,
36
+ disabledReason = "",
37
+ restrictionClass,
38
+ restrictionStyle,
31
39
  children,
40
+ "aria-describedby": ariaDescribedBy,
32
41
  ...restProps
33
42
  }: ButtonProps = $props();
34
43
 
35
- let anchorRef: HTMLAnchorElement | null = $state(null);
36
- let buttonRef: HTMLButtonElement | null = $state(null);
44
+ const restriction = $derived((disabledReason ?? "").trim());
45
+ const isDisabled = $derived(Boolean(disabled || restriction));
46
+ const restrictionId = `svadmin-button-restriction-${uid}`;
47
+ const describedBy = $derived(
48
+ [ariaDescribedBy, restriction ? restrictionId : ""].filter(Boolean).join(" ") || undefined,
49
+ );
37
50
 
38
- $effect(() => {
39
- if (href && anchorRef) ref = anchorRef as any;
40
- else if (!href && buttonRef) ref = buttonRef as any;
41
- });
51
+ function restrictionTriggerProps(props: Record<string, unknown>): Record<string, unknown> {
52
+ const next = { ...props };
53
+ delete next['type'];
54
+ delete next['role'];
55
+ delete next['disabled'];
56
+ delete next['href'];
57
+ return next;
58
+ }
42
59
  </script>
43
60
 
44
- {#if href}
45
- <a
46
- bind:this={anchorRef}
47
- data-slot="button"
48
- data-variant={variant}
49
- data-size={size}
50
- class={cn(buttonVariants({ variant, size }), className)}
51
- href={disabled ? undefined : href}
52
- aria-disabled={disabled}
53
- role={disabled ? "link" : undefined}
54
- tabindex={disabled ? -1 : undefined}
55
- {...restProps}
56
- >
57
- {@render children?.()}
58
- </a>
61
+ {#snippet control()}
62
+ {#if href}
63
+ <a
64
+ bind:this={ref}
65
+ data-slot="button"
66
+ data-variant={variant}
67
+ data-size={size}
68
+ class={cn(resolveButtonVariants({ variant, size }), className)}
69
+ href={isDisabled ? undefined : href}
70
+ aria-disabled={isDisabled ? true : undefined}
71
+ role={isDisabled ? "link" : undefined}
72
+ tabindex={isDisabled ? -1 : undefined}
73
+ aria-describedby={describedBy}
74
+ {...restProps}
75
+ onclick={(event) => {
76
+ if (isDisabled) {
77
+ event.preventDefault();
78
+ event.stopImmediatePropagation();
79
+ return;
80
+ }
81
+ restProps.onclick?.(event);
82
+ }}
83
+ >
84
+ {@render children?.()}
85
+ </a>
86
+ {:else}
87
+ <button
88
+ bind:this={ref}
89
+ data-slot="button"
90
+ data-variant={variant}
91
+ data-size={size}
92
+ class={cn(resolveButtonVariants({ variant, size }), className)}
93
+ {type}
94
+ disabled={isDisabled}
95
+ aria-describedby={describedBy}
96
+ {...restProps}
97
+ >
98
+ {@render children?.()}
99
+ </button>
100
+ {/if}
101
+ {/snippet}
102
+
103
+ {#if restriction}
104
+ <Tooltip.Root>
105
+ <Tooltip.Trigger>
106
+ {#snippet child({ props })}
107
+ {@const triggerProps = restrictionTriggerProps(props as Record<string, unknown>)}
108
+ <span
109
+ {...triggerProps}
110
+ data-slot="button-restriction"
111
+ data-disabled-reason={restriction}
112
+ role="group"
113
+ aria-label={restProps["aria-label"]}
114
+ aria-labelledby={restProps["aria-labelledby"]}
115
+ class={restrictionClass}
116
+ style={`display: inline-flex; max-width: 100%; ${restrictionStyle ?? ""}`}
117
+ aria-describedby={[triggerProps["aria-describedby"], describedBy].filter(Boolean).join(" ") || undefined}
118
+ >
119
+ {@render control()}
120
+ <span id={restrictionId} class="svadmin-sr-only">{restriction}</span>
121
+ </span>
122
+ {/snippet}
123
+ </Tooltip.Trigger>
124
+ <Tooltip.Content side="top" sideOffset={6}>{restriction}</Tooltip.Content>
125
+ </Tooltip.Root>
59
126
  {:else}
60
- <button
61
- bind:this={buttonRef}
62
- data-slot="button"
63
- data-variant={variant}
64
- data-size={size}
65
- class={cn(buttonVariants({ variant, size }), className)}
66
- {type}
67
- {disabled}
68
- {...restProps}
69
- >
70
- {@render children?.()}
71
- </button>
127
+ {@render control()}
72
128
  {/if}
@@ -1,17 +1,13 @@
1
1
  import { type WithElementRef } from "../../../utils.js";
2
2
  import type { HTMLAnchorAttributes, HTMLButtonAttributes } from "svelte/elements";
3
- import { type ButtonSize as Size, type ButtonVariant as Variant } from "./button-variants.js";
4
- export declare const buttonVariants: ({ variant, size, class: className, className: extraClassName, }?: {
5
- variant?: Variant | null;
6
- size?: Size | null;
7
- class?: Parameters<(...inputs: import("cn").ClassValue[]) => string>[number];
8
- className?: Parameters<(...inputs: import("cn").ClassValue[]) => string>[number];
9
- }) => string;
10
- export type ButtonSize = Size;
11
- export type ButtonVariant = Variant;
12
- export type ButtonProps = WithElementRef<HTMLButtonAttributes, HTMLButtonElement> & WithElementRef<HTMLAnchorAttributes, HTMLAnchorElement> & {
13
- variant?: ButtonVariant;
14
- size?: ButtonSize;
3
+ import { type ButtonSize as ButtonSizeValue, type ButtonVariant as ButtonVariantValue } from "./button-variants.js";
4
+ export { buttonVariants, type ButtonSize, type ButtonVariant } from "./button-variants.js";
5
+ export type ButtonProps = WithElementRef<HTMLButtonAttributes & HTMLAnchorAttributes, HTMLButtonElement | HTMLAnchorElement> & {
6
+ variant?: ButtonVariantValue;
7
+ size?: ButtonSizeValue;
8
+ disabledReason?: string;
9
+ restrictionClass?: string;
10
+ restrictionStyle?: string;
15
11
  };
16
12
  declare const Button: import("svelte").Component<ButtonProps, {}, "ref">;
17
13
  type Button = ReturnType<typeof Button>;
@@ -1,5 +1,3 @@
1
- /* eslint-disable @typescript-eslint/ban-ts-comment */
2
- // @ts-nocheck
3
1
  import Root, { buttonVariants, } from "./button.svelte";
4
2
  export { Root,
5
3
  //
@@ -1,4 +1,6 @@
1
1
  <script lang="ts">
2
+ import { definedOptions } from '@svadmin/core/options';
3
+
2
4
  import { Command as CommandPrimitive, Dialog as DialogPrimitive } from 'bits-ui';
3
5
  import Root from './command.svelte';
4
6
  import * as Dialog from '../dialog/index.js';
@@ -24,7 +26,7 @@
24
26
  }: Props = $props();
25
27
  </script>
26
28
 
27
- <Dialog.Dialog bind:open {onOpenChange} {onOpenChangeComplete}>
29
+ <Dialog.Dialog bind:open {...definedOptions({ "onOpenChange": onOpenChange })} {...definedOptions({ "onOpenChangeComplete": onOpenChangeComplete })}>
28
30
  <Dialog.DialogContent
29
31
  data-cmdk-dialog=""
30
32
  class="svadmin-command-dialog-content"
@@ -6,6 +6,6 @@ type Props = Omit<CommandPrimitive.RootProps, 'children' | 'value'> & Omit<Dialo
6
6
  class?: string;
7
7
  children?: Snippet;
8
8
  };
9
- declare const CommandDialog: import("svelte").Component<Props, {}, "value" | "open">;
9
+ declare const CommandDialog: import("svelte").Component<Props, {}, "open" | "value">;
10
10
  type CommandDialog = ReturnType<typeof CommandDialog>;
11
11
  export default CommandDialog;
@@ -1,4 +1,6 @@
1
1
  <script lang="ts">
2
+ import { definedOptions } from '@svadmin/core/options';
3
+
2
4
  import { Command as CommandPrimitive } from "bits-ui";
3
5
  import { cn } from "../../../utils.js";
4
6
 
@@ -22,8 +24,8 @@
22
24
  data-slot="command-group"
23
25
  data-cmdk-group=""
24
26
  class={cn("svadmin-command-group", className)}
25
- value={value ?? heading}
26
- forceMount={alwaysRender ?? forceMount}
27
+ {...definedOptions({ "value": value ?? heading })}
28
+ {...definedOptions({ "forceMount": alwaysRender ?? forceMount })}
27
29
  {...restProps}
28
30
  >
29
31
  {#if heading}
@@ -1,4 +1,6 @@
1
1
  <script lang="ts">
2
+ import { definedOptions } from '@svadmin/core/options';
3
+
2
4
  import { Command as CommandPrimitive } from "bits-ui";
3
5
  import { cn } from "../../../utils.js";
4
6
  import type { Snippet } from "svelte";
@@ -22,7 +24,7 @@
22
24
  }: Props = $props();
23
25
 
24
26
  function handleSelect() {
25
- onSelect?.(value || ref?.dataset.value || ref?.textContent?.trim() || "");
27
+ onSelect?.(value || ref?.dataset['value'] || ref?.textContent?.trim() || "");
26
28
  }
27
29
  </script>
28
30
 
@@ -32,7 +34,7 @@
32
34
  data-cmdk-item=""
33
35
  class={cn("svadmin-command-item", className)}
34
36
  {value}
35
- forceMount={alwaysRender ?? forceMount}
37
+ {...definedOptions({ "forceMount": alwaysRender ?? forceMount })}
36
38
  onSelect={handleSelect}
37
39
  {...restProps}
38
40
  >
@@ -1,4 +1,6 @@
1
1
  <script lang="ts">
2
+ import { definedOptions } from '@svadmin/core/options';
3
+
2
4
  import { Command as CommandPrimitive } from "bits-ui";
3
5
  import { cn } from "../../../utils.js";
4
6
 
@@ -18,6 +20,6 @@
18
20
  data-slot="command-separator"
19
21
  data-cmdk-separator=""
20
22
  class={cn("svadmin-command-separator", className)}
21
- forceMount={alwaysRender ?? forceMount}
23
+ {...definedOptions({ "forceMount": alwaysRender ?? forceMount })}
22
24
  {...restProps}
23
25
  />
@@ -14,7 +14,7 @@ declare const Command: {
14
14
  value?: string;
15
15
  class?: string;
16
16
  children?: import("svelte").Snippet;
17
- }, {}, "value" | "open">;
17
+ }, {}, "open" | "value">;
18
18
  Empty: import("svelte").Component<import("bits-ui").CommandEmptyProps, {}, "ref">;
19
19
  Group: import("svelte").Component<Omit<{
20
20
  value?: string;
@@ -22,8 +22,8 @@ declare const Command: {
22
22
  }, "children" | "child"> & {
23
23
  child?: import("svelte").Snippet<[{
24
24
  props: Record<string, unknown>;
25
- }]> | undefined;
26
- children?: import("svelte").Snippet<[]> | undefined;
25
+ }]>;
26
+ children?: import("svelte").Snippet<[]>;
27
27
  style?: import("bits-ui").StyleProperties | string | null | undefined;
28
28
  ref?: HTMLElement | null | undefined;
29
29
  } & import("bits-ui").Without<import("bits-ui").BitsPrimitiveDivAttributes, import("bits-ui").CommandGroupPropsWithoutHTML> & {
@@ -44,8 +44,8 @@ declare const Command: {
44
44
  }, "children" | "child"> & {
45
45
  child?: import("svelte").Snippet<[{
46
46
  props: Record<string, unknown>;
47
- }]> | undefined;
48
- children?: import("svelte").Snippet<[]> | undefined;
47
+ }]>;
48
+ children?: import("svelte").Snippet<[]>;
49
49
  style?: import("bits-ui").StyleProperties | string | null | undefined;
50
50
  ref?: HTMLElement | null | undefined;
51
51
  } & import("bits-ui").Without<import("bits-ui").BitsPrimitiveDivAttributes, import("bits-ui").CommandSeparatorPropsWithoutHTML> & {
@@ -3,43 +3,62 @@
3
3
  generics="Type extends HTMLInputTypeAttribute | undefined = undefined"
4
4
  >
5
5
  import type { HTMLInputAttributes, HTMLInputTypeAttribute } from "svelte/elements";
6
+ import { useTranslation } from "@svadmin/core/i18n";
7
+ import { definedOptions } from "@svadmin/core/options";
6
8
  import { cn, type WithElementRef } from "../../../utils.js";
7
9
 
8
- type InputValue = HTMLInputAttributes["value"];
10
+ type InputValue = Type extends "number" | "range"
11
+ ? number | null | undefined
12
+ : string | null | undefined;
9
13
 
10
- type Props = WithElementRef<
11
- Omit<HTMLInputAttributes, "type" | "value"> &
14
+ type Props = WithElementRef<Omit<HTMLInputAttributes, "type" | "value">> &
12
15
  (Type extends "file"
13
16
  ? { type: "file"; files?: FileList; value?: never }
14
- : { type?: Type; files?: undefined; value?: InputValue })
15
- >;
17
+ : { type?: Type; files?: undefined; value?: InputValue });
16
18
 
17
19
  let {
18
20
  ref = $bindable(null),
19
21
  value = $bindable(),
20
22
  type,
21
23
  files = $bindable(),
24
+ disabled,
22
25
  class: className,
23
26
  "data-slot": dataSlot = "input",
24
27
  ...restProps
25
28
  }: Props = $props();
26
29
 
30
+ const i18n = useTranslation();
27
31
  const isFileInput = $derived(type?.toLowerCase() === "file");
32
+ const isDateInput = $derived(["date", "datetime-local", "month", "week", "time"].includes(type?.toLowerCase() ?? ""));
33
+ const attributes = $derived(definedOptions({ ...restProps, disabled }));
34
+ const selectedFiles = $derived(files ? Array.from(files) : []);
35
+ const selectedFileLabel = $derived.by(() => {
36
+ const firstFile = selectedFiles[0];
37
+ if (firstFile === undefined) return i18n.t("common.noFileChosen");
38
+ if (selectedFiles.length === 1) return firstFile.name;
39
+ return i18n.t("common.filesSelected", { count: selectedFiles.length });
40
+ });
28
41
  </script>
29
42
 
30
43
  {#if isFileInput}
31
- <input
32
- bind:this={ref}
33
- data-slot={dataSlot}
34
- data-input-type="file"
35
- class={cn(
36
- "svadmin-input",
37
- className
38
- )}
39
- type="file"
40
- bind:files
41
- {...restProps}
42
- />
44
+ <div
45
+ class={cn("svadmin-file-input", className)}
46
+ data-disabled={disabled ? "true" : undefined}
47
+ >
48
+ <input
49
+ bind:this={ref}
50
+ data-slot={dataSlot}
51
+ data-input-type="file"
52
+ class={cn("svadmin-input", className)}
53
+ type="file"
54
+ bind:files
55
+ {...attributes}
56
+ />
57
+ <span class="svadmin-file-input__visual" aria-hidden="true">
58
+ <span class="svadmin-file-input__button">{i18n.t("common.chooseFile")}</span>
59
+ <span class="svadmin-file-input__name">{selectedFileLabel}</span>
60
+ </span>
61
+ </div>
43
62
  {:else}
44
63
  <input
45
64
  bind:this={ref}
@@ -48,8 +67,9 @@
48
67
  "svadmin-input",
49
68
  className
50
69
  )}
51
- {type}
52
- bind:value
53
- {...restProps}
70
+ {type}
71
+ lang={isDateInput ? i18n.locale : undefined}
72
+ bind:value
73
+ {...attributes}
54
74
  />
55
75
  {/if}
@@ -1,15 +1,16 @@
1
1
  import type { HTMLInputAttributes, HTMLInputTypeAttribute } from "svelte/elements";
2
- import { type WithElementRef } from "../../../utils.js";
3
2
  declare function $$render<Type extends HTMLInputTypeAttribute | undefined = undefined>(): {
4
- props: WithElementRef<Omit<HTMLInputAttributes, "type" | "value"> & (Type extends "file" ? {
3
+ props: Omit<HTMLInputAttributes, "type" | "value"> & {
4
+ ref?: HTMLElement | null;
5
+ } & (Type extends "file" ? {
5
6
  type: "file";
6
7
  files?: FileList;
7
8
  value?: never;
8
9
  } : {
9
10
  type?: Type;
10
11
  files?: undefined;
11
- value?: any;
12
- })>;
12
+ value?: Type extends "number" | "range" ? number | null | undefined : string | null | undefined;
13
+ });
13
14
  exports: {};
14
15
  bindings: "value" | "ref" | "files";
15
16
  slots: {};
@@ -50,6 +50,7 @@
50
50
  open?: boolean;
51
51
  side?: "left" | "right";
52
52
  onClose?: () => void;
53
+ onCloseRequest?: (close: () => void) => void;
53
54
  closeLabel?: string;
54
55
  };
55
56
 
@@ -58,6 +59,7 @@
58
59
  open = $bindable(false),
59
60
  side = "right",
60
61
  onClose,
62
+ onCloseRequest,
61
63
  closeLabel = "Close",
62
64
  class: className,
63
65
  tabindex = -1,
@@ -66,8 +68,12 @@
66
68
  }: Props = $props();
67
69
 
68
70
  function close() {
69
- open = false;
70
- onClose?.();
71
+ const commitClose = () => {
72
+ open = false;
73
+ onClose?.();
74
+ };
75
+ if (onCloseRequest) onCloseRequest(commitClose);
76
+ else commitClose();
71
77
  }
72
78
 
73
79
  function isContentEditableHost(element: HTMLElement) {
@@ -124,7 +130,7 @@
124
130
  last?.focus();
125
131
  } else if (!event.shiftKey && activeIndex === tabbable.length - 1) {
126
132
  event.preventDefault();
127
- first.focus();
133
+ first?.focus();
128
134
  }
129
135
  }
130
136
 
@@ -4,6 +4,7 @@ type Props = WithElementRef<HTMLAttributes<HTMLDivElement>> & {
4
4
  open?: boolean;
5
5
  side?: "left" | "right";
6
6
  onClose?: () => void;
7
+ onCloseRequest?: (close: () => void) => void;
7
8
  closeLabel?: string;
8
9
  };
9
10
  declare const Sheet: import("svelte").Component<Props, {}, "open" | "ref">;
@@ -1,4 +1,6 @@
1
1
  <script lang="ts" generics="Payload = never">
2
+ import { definedOptions } from '@svadmin/core/options';
3
+
2
4
  import { Tooltip as TooltipPrimitive } from "bits-ui";
3
5
  import { onDestroy } from "svelte";
4
6
  import TooltipProvider from "./tooltip-provider.svelte";
@@ -62,8 +64,8 @@
62
64
  <TooltipPrimitive.Root
63
65
  bind:open
64
66
  bind:triggerId
65
- {disableHoverableContent}
66
- {onOpenChange}
67
+ {...definedOptions({ "disableHoverableContent": disableHoverableContent })}
68
+ {...definedOptions({ "onOpenChange": onOpenChange })}
67
69
  {tether}
68
70
  {...restProps}
69
71
  />
package/dist/index.d.ts CHANGED
@@ -204,7 +204,7 @@ export { Command } from './components/ui/command/index.js';
204
204
  export { cn } from './utils';
205
205
  export { setComponentRegistry, getComponentRegistry, useComponent, type ComponentRegistry, } from './component-registry.svelte';
206
206
  export { builtinDisplayComponents, registerDisplayComponent, getDisplayComponent, hasDisplayComponent, } from './components/fieldComponentMap';
207
- export type { FieldComponentMap } from './components/fieldComponentMap';
207
+ export type { FieldComponentMap, FieldDisplayProps } from './components/fieldComponentMap';
208
208
  export { clickOutside, shortcut, intersect, copyOnClick } from './actions';
209
209
  export { default as ProfileCard } from './components/profile/ProfileCard.svelte';
210
210
  export { default as ProjectsGrid } from './components/profile/ProjectsGrid.svelte';
@@ -0,0 +1,5 @@
1
+ export declare function inlineDisplayValue(type: string, value: unknown): {
2
+ text: string;
3
+ value: string | number | null;
4
+ } | undefined;
5
+ export declare function parseInlineValue(type: string, text: string): string | number | null;
@@ -0,0 +1,24 @@
1
+ import { numericInputValue } from './numeric-input';
2
+ export function inlineDisplayValue(type, value) {
3
+ if (!['number', 'text', 'email', 'url'].includes(type))
4
+ return undefined;
5
+ if (value === null || value === undefined)
6
+ return { text: '', value: null };
7
+ if (type === 'number')
8
+ return typeof value === 'number' && Number.isFinite(value)
9
+ ? { text: String(value), value } : undefined;
10
+ return typeof value === 'string' ? { text: value, value } : undefined;
11
+ }
12
+ export function parseInlineValue(type, text) {
13
+ if (type === 'number') {
14
+ const value = text.trim();
15
+ if (!value)
16
+ return null;
17
+ if (!/^[+-]?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?$/.test(value))
18
+ throw new TypeError('Invalid numeric input');
19
+ return numericInputValue(Number(value));
20
+ }
21
+ if (type === 'text' || type === 'email' || type === 'url')
22
+ return text;
23
+ throw new TypeError('Unsupported inline field');
24
+ }
@@ -0,0 +1,2 @@
1
+ /** Empty form values are null; nonempty values must already be finite numbers. */
2
+ export declare function numericInputValue(value: unknown): number | null;
@@ -0,0 +1,9 @@
1
+ /** Empty form values are null; nonempty values must already be finite numbers. */
2
+ export function numericInputValue(value) {
3
+ if (value === null || value === undefined || value === '')
4
+ return null;
5
+ if (typeof value !== 'number' || !Number.isFinite(value)) {
6
+ throw new TypeError('Numeric inputs require a finite number or an empty value');
7
+ }
8
+ return value;
9
+ }
package/dist/types.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import type { I18nProvider, ProviderBundle } from '@svadmin/core';
2
2
  /**
3
- * AdminApp 的可组合 provider 配置。
3
+ * Composable provider configuration for AdminApp.
4
4
  *
5
- * 旧版顶层 props 仍然可用,且在同时传入时优先于这里的同名配置。
6
- * Access control 仅控制浏览器端呈现,后端仍必须独立鉴权。
5
+ * Legacy top-level props remain supported and take precedence over matching fields here when both are provided.
6
+ * Access control only affects browser rendering; the backend must still authenticate independently.
7
7
  */
8
8
  export type AdminProviderBundle = ProviderBundle & {
9
9
  /** UI-only locale integration; all other fields come from Core's canonical ProviderBundle. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@svadmin/ui",
3
- "version": "0.69.1",
3
+ "version": "0.72.0",
4
4
  "description": "Pre-built admin UI components — AdminApp, AutoTable, AutoForm, Sidebar, Layout",
5
5
  "type": "module",
6
6
  "sideEffects": [
@@ -32,6 +32,11 @@
32
32
  "style": "./dist/app.theme.css",
33
33
  "default": "./dist/app.theme.css"
34
34
  },
35
+ "./editor-config": {
36
+ "types": "./dist/editor-config.svelte.d.ts",
37
+ "svelte": "./dist/editor-config.svelte.js",
38
+ "default": "./dist/editor-config.svelte.js"
39
+ },
35
40
  "./components/*.svelte": {
36
41
  "types": "./dist/components/*.svelte.d.ts",
37
42
  "svelte": "./dist/components/*.svelte",
@@ -40,7 +45,7 @@
40
45
  "./components/*": "./dist/components/*"
41
46
  },
42
47
  "peerDependencies": {
43
- "@svadmin/core": "^0.49.1",
48
+ "@svadmin/core": "^0.52.0",
44
49
  "@tanstack/svelte-query": "^6.1.48",
45
50
  "isomorphic-dompurify": "^3.23.0",
46
51
  "svelte": "^5.56.10"
@@ -63,6 +68,7 @@
63
68
  }
64
69
  },
65
70
  "dependencies": {
71
+ "@sinclair/typebox": "^0.34.52",
66
72
  "@floating-ui/dom": "^1.8.0",
67
73
  "@lucide/svelte": "^1.35.0",
68
74
  "@tanstack/svelte-store": "^0.12.1",
@@ -76,7 +82,7 @@
76
82
  "author": "zuohuadong",
77
83
  "repository": {
78
84
  "type": "git",
79
- "url": "https://github.com/vibeunion/svadmin.git",
85
+ "url": "git+https://github.com/vibeunion/svadmin.git",
80
86
  "directory": "packages/ui"
81
87
  },
82
88
  "homepage": "https://github.com/vibeunion/svadmin#readme",
@@ -88,16 +94,16 @@
88
94
  },
89
95
  "devDependencies": {
90
96
  "@happy-dom/global-registrator": "^20.11.12",
91
- "@svadmin/ai-elements": "^0.5.0",
97
+ "@svadmin/ai-elements": "^0.7.4",
92
98
  "@sveltejs/vite-plugin-svelte": "^7.3.0",
93
99
  "@tailwindcss/node": "^4.3.3",
100
+ "tailwindcss": "^4.3.3",
94
101
  "@testing-library/dom": "^10.4.1",
95
102
  "@testing-library/svelte": "^5.4.2",
96
103
  "@testing-library/user-event": "^14.6.6",
97
104
  "happy-dom": "^20.11.12",
98
105
  "postcss": "^8.5.26",
99
106
  "postcss-selector-parser": "^7.1.1",
100
- "tailwindcss": "^4.3.3",
101
107
  "tw-animate-css": "^1.4.0",
102
108
  "vitest": "^4.1.11"
103
109
  },