@riducms/admin 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +31 -0
- package/THIRD_PARTY_NOTICES.md +217 -0
- package/package.json +62 -0
- package/src/app/admin-core-view-route.svelte +89 -0
- package/src/app/admin-layout.svelte +457 -0
- package/src/app/admin-navigation-progress.svelte +204 -0
- package/src/app/admin-page-title.svelte +94 -0
- package/src/app/admin-provider-layer.svelte +26 -0
- package/src/app/admin-router-root.svelte +9 -0
- package/src/app/admin-routes.svelte +116 -0
- package/src/app/deferred-redirect.svelte +23 -0
- package/src/app/loading-boundary.svelte +70 -0
- package/src/app/not-found-route.svelte +29 -0
- package/src/app-meta.ts +2 -0
- package/src/app.css +467 -0
- package/src/app.svelte +88 -0
- package/src/assets/ridu-logo-arch.svg +3 -0
- package/src/assets/ridu-word-logo.svg +7 -0
- package/src/components/brand/ridu-logo.svelte +24 -0
- package/src/components/code-block/code-block.svelte +107 -0
- package/src/components/json-tree/json-tree-node.svelte +77 -0
- package/src/components/json-tree/json-viewer.svelte +113 -0
- package/src/components/ui/banner/banner.svelte +41 -0
- package/src/components/ui/banner/index.ts +5 -0
- package/src/components/ui/bulk-action-bar/bulk-action-bar.svelte +50 -0
- package/src/components/ui/bulk-action-bar/index.ts +1 -0
- package/src/components/ui/button/index.ts +8 -0
- package/src/components/ui/calendar/calendar-caption.svelte +72 -0
- package/src/components/ui/calendar/calendar-cell.svelte +20 -0
- package/src/components/ui/calendar/calendar-day.svelte +27 -0
- package/src/components/ui/calendar/calendar-grid-row.svelte +13 -0
- package/src/components/ui/calendar/calendar-grid.svelte +17 -0
- package/src/components/ui/calendar/calendar-head-cell.svelte +20 -0
- package/src/components/ui/calendar/calendar-header.svelte +20 -0
- package/src/components/ui/calendar/calendar-heading.svelte +17 -0
- package/src/components/ui/calendar/calendar-month-select.svelte +45 -0
- package/src/components/ui/calendar/calendar-month.svelte +16 -0
- package/src/components/ui/calendar/calendar-months.svelte +20 -0
- package/src/components/ui/calendar/calendar-nav.svelte +20 -0
- package/src/components/ui/calendar/calendar-next-button.svelte +30 -0
- package/src/components/ui/calendar/calendar-prev-button.svelte +30 -0
- package/src/components/ui/calendar/calendar-year-select.svelte +44 -0
- package/src/components/ui/calendar/calendar.svelte +118 -0
- package/src/components/ui/calendar/index.ts +1 -0
- package/src/components/ui/checkbox/checkbox.svelte +35 -0
- package/src/components/ui/checkbox/index.ts +1 -0
- package/src/components/ui/confirmation-dialog/confirmation-dialog.svelte +37 -0
- package/src/components/ui/confirmation-dialog/index.ts +1 -0
- package/src/components/ui/date-value-control/date-value-calendar.svelte +37 -0
- package/src/components/ui/date-value-control/date-value-control-loader.svelte +36 -0
- package/src/components/ui/date-value-control/date-value-control.svelte +177 -0
- package/src/components/ui/date-value-control/index.ts +3 -0
- package/src/components/ui/dialog/dialog-close.svelte +11 -0
- package/src/components/ui/dialog/dialog-content.svelte +52 -0
- package/src/components/ui/dialog/dialog-description.svelte +20 -0
- package/src/components/ui/dialog/dialog-footer.svelte +20 -0
- package/src/components/ui/dialog/dialog-header.svelte +20 -0
- package/src/components/ui/dialog/dialog-overlay.svelte +20 -0
- package/src/components/ui/dialog/dialog-title.svelte +17 -0
- package/src/components/ui/dialog/dialog-trigger.svelte +11 -0
- package/src/components/ui/dialog/dialog.svelte +7 -0
- package/src/components/ui/dialog/index.ts +8 -0
- package/src/components/ui/dropdown-menu/dropdown-menu-content.svelte +27 -0
- package/src/components/ui/dropdown-menu/dropdown-menu-item.svelte +20 -0
- package/src/components/ui/dropdown-menu/dropdown-menu-separator.svelte +17 -0
- package/src/components/ui/dropdown-menu/dropdown-menu-trigger.svelte +16 -0
- package/src/components/ui/dropdown-menu/dropdown-menu.svelte +7 -0
- package/src/components/ui/dropdown-menu/index.ts +5 -0
- package/src/components/ui/empty-state/empty-state.svelte +34 -0
- package/src/components/ui/empty-state/index.ts +1 -0
- package/src/components/ui/input/index.ts +1 -0
- package/src/components/ui/kbd/index.ts +1 -0
- package/src/components/ui/kbd/kbd.svelte +24 -0
- package/src/components/ui/pagination/index.ts +1 -0
- package/src/components/ui/pagination/pagination.svelte +88 -0
- package/src/components/ui/popover/index.ts +3 -0
- package/src/components/ui/popover/popover-content.svelte +29 -0
- package/src/components/ui/popover/popover-trigger.svelte +11 -0
- package/src/components/ui/popover/popover.svelte +7 -0
- package/src/components/ui/radio-group/index.ts +3 -0
- package/src/components/ui/radio-group/radio-card-item.svelte +38 -0
- package/src/components/ui/radio-group/radio-group-item.svelte +17 -0
- package/src/components/ui/radio-group/radio-group.svelte +19 -0
- package/src/components/ui/select/index.ts +4 -0
- package/src/components/ui/select/select-content.svelte +38 -0
- package/src/components/ui/select/select-item.svelte +40 -0
- package/src/components/ui/select/select-scroll-down-button.svelte +23 -0
- package/src/components/ui/select/select-scroll-up-button.svelte +23 -0
- package/src/components/ui/select/select-trigger.svelte +29 -0
- package/src/components/ui/select/select.svelte +11 -0
- package/src/components/ui/sheet/index.ts +6 -0
- package/src/components/ui/sheet/sheet-close.svelte +7 -0
- package/src/components/ui/sheet/sheet-content.svelte +77 -0
- package/src/components/ui/sheet/sheet-description.svelte +17 -0
- package/src/components/ui/sheet/sheet-overlay.svelte +36 -0
- package/src/components/ui/sheet/sheet-title.svelte +17 -0
- package/src/components/ui/sheet/sheet-trigger.svelte +7 -0
- package/src/components/ui/sheet/sheet.svelte +7 -0
- package/src/components/ui/skeleton/index.ts +1 -0
- package/src/components/ui/skeleton/skeleton.svelte +31 -0
- package/src/components/ui/slider/index.ts +3 -0
- package/src/components/ui/slider/slider-content.svelte +59 -0
- package/src/components/ui/slider/slider.svelte +35 -0
- package/src/components/ui/sonner/index.ts +1 -0
- package/src/components/ui/sonner/sonner.svelte +55 -0
- package/src/components/ui/status-indicator/index.ts +5 -0
- package/src/components/ui/status-indicator/status-indicator.svelte +54 -0
- package/src/components/ui/table/index.ts +6 -0
- package/src/components/ui/table/table-body.svelte +20 -0
- package/src/components/ui/table/table-cell.svelte +23 -0
- package/src/components/ui/table/table-head.svelte +23 -0
- package/src/components/ui/table/table-header.svelte +20 -0
- package/src/components/ui/table/table-row.svelte +23 -0
- package/src/components/ui/table/table.svelte +22 -0
- package/src/components/ui/tabs/index.ts +8 -0
- package/src/components/ui/tabs/tabs-content.svelte +17 -0
- package/src/components/ui/tabs/tabs-list.svelte +40 -0
- package/src/components/ui/tabs/tabs-trigger.svelte +23 -0
- package/src/components/ui/tabs/tabs.svelte +19 -0
- package/src/components/ui/textarea/index.ts +1 -0
- package/src/components/ui/tooltip/index.ts +4 -0
- package/src/components/ui/tooltip/tooltip-content.svelte +50 -0
- package/src/components/ui/tooltip/tooltip-provider.svelte +7 -0
- package/src/components/ui/tooltip/tooltip-trigger.svelte +7 -0
- package/src/components/ui/tooltip/tooltip.svelte +7 -0
- package/src/core/api/admin-client.ts +45 -0
- package/src/core/forms/field-condition.ts +63 -0
- package/src/core/forms/form-controller.svelte.ts +369 -0
- package/src/core/forms/form-draft-recovery.ts +80 -0
- package/src/core/forms/form-schema.ts +609 -0
- package/src/core/forms/form-validation.ts +750 -0
- package/src/core/i18n/admin-i18n.svelte.ts +364 -0
- package/src/core/i18n/localized-schema.ts +111 -0
- package/src/core/notifications/notification-center.svelte.ts +69 -0
- package/src/core/notifications/validation-toast.svelte +18 -0
- package/src/core/plugins/field-registry.ts +60 -0
- package/src/core/plugins/row-label-registry.ts +62 -0
- package/src/core/preferences/preference-write-queue.ts +107 -0
- package/src/core/routing/admin-paths.ts +137 -0
- package/src/core/runtime/admin-runtime.svelte.ts +625 -0
- package/src/features/auth/account-menu.svelte +159 -0
- package/src/features/auth/account-navigation.svelte +44 -0
- package/src/features/auth/account-route.svelte +395 -0
- package/src/features/auth/account-security-controller.svelte.ts +119 -0
- package/src/features/auth/account-security-route.svelte +460 -0
- package/src/features/auth/auth-brand.svelte +17 -0
- package/src/features/auth/auth-frame.svelte +18 -0
- package/src/features/auth/create-first-user-controller.svelte.ts +220 -0
- package/src/features/auth/create-first-user-route.svelte +174 -0
- package/src/features/auth/forgot-password-route.svelte +78 -0
- package/src/features/auth/login-route.svelte +221 -0
- package/src/features/auth/request-verification-route.svelte +73 -0
- package/src/features/auth/reset-password-route.svelte +107 -0
- package/src/features/auth/verify-email-route.svelte +60 -0
- package/src/features/collections/collection-list-bulk-actions.svelte +143 -0
- package/src/features/collections/collection-list-bulk-editor.svelte +157 -0
- package/src/features/collections/collection-list-controller.svelte.ts +717 -0
- package/src/features/collections/collection-list-filter-popover.svelte +238 -0
- package/src/features/collections/collection-list-preferences-controller.svelte.ts +393 -0
- package/src/features/collections/collection-list-results.svelte +410 -0
- package/src/features/collections/collection-list-route.svelte +951 -0
- package/src/features/collections/collection-list-workspace-toolbar.svelte +409 -0
- package/src/features/collections/collection-table-skeleton.svelte +44 -0
- package/src/features/collections/list-workspace.ts +265 -0
- package/src/features/dashboard/dashboard-route.svelte +141 -0
- package/src/features/development/development-tools.svelte +217 -0
- package/src/features/documents/document-api-view-loader.svelte +31 -0
- package/src/features/documents/document-api-view.svelte +547 -0
- package/src/features/documents/document-controller.svelte.ts +1252 -0
- package/src/features/documents/document-field-partition.ts +18 -0
- package/src/features/documents/document-field-sections.svelte +46 -0
- package/src/features/documents/document-heading.ts +20 -0
- package/src/features/documents/document-route-dirty.ts +43 -0
- package/src/features/documents/document-route-loader.svelte +22 -0
- package/src/features/documents/document-route.svelte +1124 -0
- package/src/features/documents/live-preview-panel.svelte +390 -0
- package/src/features/documents/live-preview.ts +61 -0
- package/src/features/documents/upload-document-preview-loader.svelte +40 -0
- package/src/features/documents/upload-document-preview.svelte +525 -0
- package/src/features/localization/content-locale-switcher.svelte +93 -0
- package/src/features/navigation/admin-breadcrumbs.svelte +124 -0
- package/src/features/navigation/admin-command-menu.svelte +245 -0
- package/src/features/navigation/admin-resource-groups.ts +72 -0
- package/src/features/reference-browser/reference-browser-loader.svelte +15 -0
- package/src/features/reference-browser/reference-browser-workflow.svelte.ts +691 -0
- package/src/features/reference-browser/reference-browser.svelte +844 -0
- package/src/features/uploads/bulk-upload-route.svelte +624 -0
- package/src/features/uploads/bulk-upload.ts +39 -0
- package/src/features/uploads/upload-metadata-fields.svelte +112 -0
- package/src/features/versions/version-diff.ts +72 -0
- package/src/features/versions/version-history-route.svelte +581 -0
- package/src/fields/field-clipboard.ts +132 -0
- package/src/fields/field-layout.svelte +60 -0
- package/src/fields/field-layout.ts +57 -0
- package/src/fields/field-messages.svelte +29 -0
- package/src/fields/field-renderer.svelte +152 -0
- package/src/fields/field-shell.svelte +30 -0
- package/src/fields/field-tab-layout.svelte +99 -0
- package/src/fields/join/join-field.svelte +358 -0
- package/src/fields/localized-field-presentation.ts +17 -0
- package/src/fields/nested/nested-field.svelte +602 -0
- package/src/fields/nested/scoped-field.ts +78 -0
- package/src/fields/nested/sortable-row.svelte +32 -0
- package/src/fields/point/point-field.svelte +52 -0
- package/src/fields/radio/radio-field.svelte +34 -0
- package/src/fields/relationship/relationship-field-controller.svelte.ts +245 -0
- package/src/fields/relationship/relationship-field.svelte +258 -0
- package/src/fields/relationship/relationship-lookup-controller.svelte.ts +129 -0
- package/src/fields/relationship/relationship-query.ts +88 -0
- package/src/fields/relationship/relationship-quick-picker-controller.svelte.ts +198 -0
- package/src/fields/relationship/relationship-quick-picker.svelte +327 -0
- package/src/fields/relationship/relationship-value.ts +47 -0
- package/src/fields/scalar/date-control-value.ts +60 -0
- package/src/fields/scalar/date-value.ts +26 -0
- package/src/fields/scalar/scalar-field.svelte +137 -0
- package/src/fields/select/select-field.svelte +132 -0
- package/src/fields/select/select-value.ts +14 -0
- package/src/fields/text/slug-field.svelte +87 -0
- package/src/fields/text/slug.ts +38 -0
- package/src/fields/text/text-field.svelte +41 -0
- package/src/fields/ui/ui-field.svelte +12 -0
- package/src/fields/virtual/virtual-field.svelte +28 -0
- package/src/index.ts +49 -0
- package/src/main.ts +12 -0
- package/src/vite-env.d.ts +9 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import ChevronRightIcon from "~icons/lucide/chevron-right";
|
|
3
|
+
|
|
4
|
+
import JsonTreeNode from "@admin/components/json-tree/json-tree-node.svelte";
|
|
5
|
+
|
|
6
|
+
let { name, value, last = true }: { name?: string; value: unknown; last?: boolean } = $props();
|
|
7
|
+
const entries = $derived(
|
|
8
|
+
Array.isArray(value)
|
|
9
|
+
? value.map((item, index) => [String(index), item] as const)
|
|
10
|
+
: isRecord(value)
|
|
11
|
+
? Object.entries(value)
|
|
12
|
+
: []
|
|
13
|
+
);
|
|
14
|
+
const container = $derived(Array.isArray(value) || isRecord(value));
|
|
15
|
+
const opening = $derived(Array.isArray(value) ? "[" : "{");
|
|
16
|
+
const closing = $derived(Array.isArray(value) ? "]" : "}");
|
|
17
|
+
const countLabel = $derived(
|
|
18
|
+
Array.isArray(value)
|
|
19
|
+
? entries.length === 1
|
|
20
|
+
? "item"
|
|
21
|
+
: "items"
|
|
22
|
+
: entries.length === 1
|
|
23
|
+
? "key"
|
|
24
|
+
: "keys"
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
function isRecord(candidate: unknown): candidate is Record<string, unknown> {
|
|
28
|
+
return typeof candidate === "object" && candidate !== null && !Array.isArray(candidate);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function primitive(candidate: unknown) {
|
|
32
|
+
if (typeof candidate === "string") return JSON.stringify(candidate);
|
|
33
|
+
if (candidate === undefined) return "undefined";
|
|
34
|
+
return String(candidate);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function tone(candidate: unknown) {
|
|
38
|
+
if (typeof candidate === "string") return "text-[#b7c89a]";
|
|
39
|
+
if (typeof candidate === "number") return "text-[#c9b38b]";
|
|
40
|
+
if (typeof candidate === "boolean") return "text-[#9fb9d8]";
|
|
41
|
+
return "text-foreground-faint";
|
|
42
|
+
}
|
|
43
|
+
</script>
|
|
44
|
+
|
|
45
|
+
{#if container}
|
|
46
|
+
<details class="group/json" open>
|
|
47
|
+
<summary
|
|
48
|
+
class="flex cursor-pointer list-none items-center gap-1 rounded px-0.5 hover:bg-control-hover focus-visible:outline-1 focus-visible:outline-primary/60"
|
|
49
|
+
aria-label={name === undefined
|
|
50
|
+
? `${entries.length} ${countLabel}`
|
|
51
|
+
: `${name}, ${entries.length} ${countLabel}`}
|
|
52
|
+
>
|
|
53
|
+
<ChevronRightIcon
|
|
54
|
+
class="size-3 shrink-0 text-foreground-faint transition-transform group-open/json:rotate-90"
|
|
55
|
+
/>
|
|
56
|
+
{#if name !== undefined}<span class="text-[#9db5cd]">{JSON.stringify(name)}</span>
|
|
57
|
+
<span class="text-foreground-faint">:</span>{/if}
|
|
58
|
+
<span class="text-foreground-muted">{opening}</span>
|
|
59
|
+
<span class="text-[10px] text-foreground-faint">
|
|
60
|
+
{entries.length}
|
|
61
|
+
{countLabel}
|
|
62
|
+
</span>
|
|
63
|
+
<span class="text-foreground-muted">{closing}{last ? "" : ","}</span>
|
|
64
|
+
</summary>
|
|
65
|
+
<div class="ms-3.5 border-s border-control-border ps-3">
|
|
66
|
+
{#each entries as [key, child], index (key)}
|
|
67
|
+
<JsonTreeNode name={key} value={child} last={index === entries.length - 1} />
|
|
68
|
+
{/each}
|
|
69
|
+
</div>
|
|
70
|
+
</details>
|
|
71
|
+
{:else}
|
|
72
|
+
<div class="flex gap-1 rounded px-0.5 hover:bg-control-hover">
|
|
73
|
+
{#if name !== undefined}<span class="text-[#9db5cd]">{JSON.stringify(name)}</span>
|
|
74
|
+
<span class="text-foreground-faint">:</span>{/if}
|
|
75
|
+
<span class={tone(value)}>{primitive(value)}{last ? "" : ","}</span>
|
|
76
|
+
</div>
|
|
77
|
+
{/if}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { onDestroy } from "svelte";
|
|
3
|
+
import CheckIcon from "~icons/lucide/check";
|
|
4
|
+
import CopyIcon from "~icons/lucide/copy";
|
|
5
|
+
import Maximize2Icon from "~icons/lucide/maximize-2";
|
|
6
|
+
import Minimize2Icon from "~icons/lucide/minimize-2";
|
|
7
|
+
import { getAdminI18n } from "@riducms/plugin";
|
|
8
|
+
|
|
9
|
+
import JsonTreeNode from "@admin/components/json-tree/json-tree-node.svelte";
|
|
10
|
+
import { Button, buttonVariants } from "@admin/components/ui/button";
|
|
11
|
+
import {
|
|
12
|
+
Dialog,
|
|
13
|
+
DialogClose,
|
|
14
|
+
DialogContent,
|
|
15
|
+
DialogDescription,
|
|
16
|
+
DialogTitle,
|
|
17
|
+
DialogTrigger,
|
|
18
|
+
} from "@admin/components/ui/dialog";
|
|
19
|
+
|
|
20
|
+
let { value, class: className = "" }: { value: unknown; class?: string } = $props();
|
|
21
|
+
const i18n = getAdminI18n();
|
|
22
|
+
let copied = $state(false);
|
|
23
|
+
let copyFailed = $state(false);
|
|
24
|
+
let copyResetTimer: ReturnType<typeof setTimeout> | undefined;
|
|
25
|
+
|
|
26
|
+
onDestroy(() => clearTimeout(copyResetTimer));
|
|
27
|
+
|
|
28
|
+
async function copy() {
|
|
29
|
+
try {
|
|
30
|
+
await navigator.clipboard.writeText(JSON.stringify(value, null, 2));
|
|
31
|
+
copied = true;
|
|
32
|
+
copyFailed = false;
|
|
33
|
+
} catch {
|
|
34
|
+
copyFailed = true;
|
|
35
|
+
}
|
|
36
|
+
clearTimeout(copyResetTimer);
|
|
37
|
+
copyResetTimer = window.setTimeout(() => {
|
|
38
|
+
copied = false;
|
|
39
|
+
copyFailed = false;
|
|
40
|
+
}, 1_500);
|
|
41
|
+
}
|
|
42
|
+
</script>
|
|
43
|
+
|
|
44
|
+
{#snippet viewer(expanded: boolean)}
|
|
45
|
+
<div
|
|
46
|
+
class={[
|
|
47
|
+
"flex min-h-0 flex-col overflow-hidden rounded-[4px] border border-control-border bg-control",
|
|
48
|
+
!expanded && className,
|
|
49
|
+
expanded && "h-full rounded-none border-0 bg-background",
|
|
50
|
+
]}
|
|
51
|
+
>
|
|
52
|
+
<div class="flex items-center justify-between border-b border-control-border px-3 py-2">
|
|
53
|
+
<span class="font-mono text-[9.5px] tracking-[0.12em] text-foreground-faint uppercase">
|
|
54
|
+
JSON
|
|
55
|
+
</span>
|
|
56
|
+
<div class="flex items-center gap-1">
|
|
57
|
+
{#if expanded}
|
|
58
|
+
<DialogClose
|
|
59
|
+
class={buttonVariants({ variant: "ghost", size: "icon-xs" })}
|
|
60
|
+
aria-label={i18n.t("general:exitExpandedJSONView")}
|
|
61
|
+
title={i18n.t("general:exitExpandedJSONView")}
|
|
62
|
+
>
|
|
63
|
+
<Minimize2Icon class="size-3.5" />
|
|
64
|
+
</DialogClose>
|
|
65
|
+
{:else}
|
|
66
|
+
<DialogTrigger
|
|
67
|
+
class={buttonVariants({ variant: "ghost", size: "icon-xs" })}
|
|
68
|
+
aria-label={i18n.t("general:expandJSONView")}
|
|
69
|
+
title={i18n.t("general:expandJSONView")}
|
|
70
|
+
>
|
|
71
|
+
<Maximize2Icon class="size-3.5" />
|
|
72
|
+
</DialogTrigger>
|
|
73
|
+
{/if}
|
|
74
|
+
<Button
|
|
75
|
+
variant="ghost"
|
|
76
|
+
size="xs"
|
|
77
|
+
onclick={copy}
|
|
78
|
+
aria-label={i18n.t("general:copyJSON")}
|
|
79
|
+
tooltip={copied
|
|
80
|
+
? i18n.t("general:copied")
|
|
81
|
+
: copyFailed
|
|
82
|
+
? i18n.t("general:copyUnavailable")
|
|
83
|
+
: i18n.t("general:copyJSON")}
|
|
84
|
+
>
|
|
85
|
+
{#if copied}<CheckIcon class="size-3" /> {i18n.t("general:copied")}{:else}<CopyIcon
|
|
86
|
+
class="size-3"
|
|
87
|
+
/>
|
|
88
|
+
{copyFailed ? i18n.t("general:copyUnavailable") : i18n.t("general:copy")}{/if}
|
|
89
|
+
</Button>
|
|
90
|
+
</div>
|
|
91
|
+
</div>
|
|
92
|
+
<section
|
|
93
|
+
class="min-h-72 flex-1 overflow-auto p-4 font-mono text-[11.5px] leading-6"
|
|
94
|
+
aria-label={i18n.t("general:jsonData")}
|
|
95
|
+
>
|
|
96
|
+
<JsonTreeNode {value} />
|
|
97
|
+
</section>
|
|
98
|
+
</div>
|
|
99
|
+
{/snippet}
|
|
100
|
+
|
|
101
|
+
<Dialog>
|
|
102
|
+
{@render viewer(false)}
|
|
103
|
+
<DialogContent
|
|
104
|
+
showCloseButton={false}
|
|
105
|
+
class="inset-3 top-3 left-3 h-auto w-auto max-w-none translate-x-0 translate-y-0 gap-0 overflow-hidden p-0 sm:max-w-none"
|
|
106
|
+
>
|
|
107
|
+
<DialogTitle class="sr-only">{i18n.t("general:expandedJSONResponse")}</DialogTitle>
|
|
108
|
+
<DialogDescription class="sr-only">
|
|
109
|
+
{i18n.t("general:expandedJSONDescription")}
|
|
110
|
+
</DialogDescription>
|
|
111
|
+
{@render viewer(true)}
|
|
112
|
+
</DialogContent>
|
|
113
|
+
</Dialog>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
import { tv, type VariantProps } from "@riducms/ui";
|
|
3
|
+
|
|
4
|
+
export const bannerVariants = tv({
|
|
5
|
+
base: "flex min-w-0 items-start gap-3 rounded-[3px] border px-3.5 py-3 text-[13.5px] leading-5",
|
|
6
|
+
variants: {
|
|
7
|
+
tone: {
|
|
8
|
+
warning: "border-warning/30 bg-warning/8 text-warning",
|
|
9
|
+
destructive: "border-destructive/30 bg-destructive/8 text-destructive",
|
|
10
|
+
neutral: "border-border bg-muted/35 text-foreground-muted",
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
defaultVariants: { tone: "neutral" },
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
export type BannerTone = VariantProps<typeof bannerVariants>["tone"];
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
<script lang="ts">
|
|
20
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
21
|
+
|
|
22
|
+
import { cn, type WithElementRef } from "@riducms/ui";
|
|
23
|
+
|
|
24
|
+
let {
|
|
25
|
+
ref = $bindable(null),
|
|
26
|
+
tone = "neutral",
|
|
27
|
+
class: className,
|
|
28
|
+
children,
|
|
29
|
+
...restProps
|
|
30
|
+
}: WithElementRef<HTMLAttributes<HTMLDivElement>> & { tone?: BannerTone } = $props();
|
|
31
|
+
</script>
|
|
32
|
+
|
|
33
|
+
<div
|
|
34
|
+
bind:this={ref}
|
|
35
|
+
data-slot="banner"
|
|
36
|
+
class={cn(bannerVariants({ tone }), className)}
|
|
37
|
+
role={tone === "destructive" ? "alert" : "status"}
|
|
38
|
+
{...restProps}
|
|
39
|
+
>
|
|
40
|
+
{@render children?.()}
|
|
41
|
+
</div>
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import XIcon from "~icons/lucide/x";
|
|
3
|
+
import type { Snippet } from "svelte";
|
|
4
|
+
import { getAdminI18n } from "@riducms/plugin";
|
|
5
|
+
|
|
6
|
+
import { Button } from "@admin/components/ui/button";
|
|
7
|
+
|
|
8
|
+
let {
|
|
9
|
+
count,
|
|
10
|
+
onClear,
|
|
11
|
+
label,
|
|
12
|
+
selectionLabel,
|
|
13
|
+
clearLabel,
|
|
14
|
+
children,
|
|
15
|
+
}: {
|
|
16
|
+
count: number;
|
|
17
|
+
onClear: () => void;
|
|
18
|
+
label?: string;
|
|
19
|
+
selectionLabel?: string;
|
|
20
|
+
clearLabel?: string;
|
|
21
|
+
children?: Snippet;
|
|
22
|
+
} = $props();
|
|
23
|
+
const i18n = getAdminI18n();
|
|
24
|
+
const resolvedLabel = $derived(label ?? i18n.t("general:bulkActions"));
|
|
25
|
+
const resolvedSelectionLabel = $derived(selectionLabel ?? i18n.t("general:selected", { count }));
|
|
26
|
+
const resolvedClearLabel = $derived(clearLabel ?? i18n.t("general:clearSelection"));
|
|
27
|
+
</script>
|
|
28
|
+
|
|
29
|
+
{#if count > 0}
|
|
30
|
+
<div
|
|
31
|
+
data-slot="bulk-action-bar"
|
|
32
|
+
class="ridu-popover-enter fixed bottom-6 left-1/2 z-40 flex max-w-[calc(100vw-2rem)] -translate-x-1/2 items-center gap-2 rounded-[4px] border border-control-border bg-popover px-3 py-2 text-popover-foreground shadow-[var(--shadow-popover)]"
|
|
33
|
+
role="region"
|
|
34
|
+
aria-label={resolvedLabel}
|
|
35
|
+
>
|
|
36
|
+
<span
|
|
37
|
+
class="whitespace-nowrap px-2 text-[13.5px] font-medium text-foreground"
|
|
38
|
+
role="status"
|
|
39
|
+
aria-live="polite"
|
|
40
|
+
aria-atomic="true"
|
|
41
|
+
>
|
|
42
|
+
{resolvedSelectionLabel}
|
|
43
|
+
</span>
|
|
44
|
+
<span class="h-5 w-px bg-control-border" aria-hidden="true"></span>
|
|
45
|
+
{@render children?.()}
|
|
46
|
+
<Button variant="ghost" size="icon-sm" onclick={onClear} aria-label={resolvedClearLabel}>
|
|
47
|
+
<XIcon class="size-3.5" />
|
|
48
|
+
</Button>
|
|
49
|
+
</div>
|
|
50
|
+
{/if}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as BulkActionBar } from "@admin/components/ui/bulk-action-bar/bulk-action-bar.svelte";
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { DateFormatter, getLocalTimeZone, type DateValue } from "@internationalized/date";
|
|
3
|
+
import type { ComponentProps } from "svelte";
|
|
4
|
+
|
|
5
|
+
import CalendarMonthSelect from "@admin/components/ui/calendar/calendar-month-select.svelte";
|
|
6
|
+
import CalendarYearSelect from "@admin/components/ui/calendar/calendar-year-select.svelte";
|
|
7
|
+
import type Calendar from "@admin/components/ui/calendar/calendar.svelte";
|
|
8
|
+
|
|
9
|
+
let {
|
|
10
|
+
captionLayout,
|
|
11
|
+
months,
|
|
12
|
+
monthFormat,
|
|
13
|
+
years,
|
|
14
|
+
yearFormat,
|
|
15
|
+
month,
|
|
16
|
+
locale,
|
|
17
|
+
placeholder = $bindable(),
|
|
18
|
+
monthIndex = 0,
|
|
19
|
+
}: {
|
|
20
|
+
captionLayout: ComponentProps<typeof Calendar>["captionLayout"];
|
|
21
|
+
months: ComponentProps<typeof CalendarMonthSelect>["months"];
|
|
22
|
+
monthFormat: ComponentProps<typeof CalendarMonthSelect>["monthFormat"];
|
|
23
|
+
years: ComponentProps<typeof CalendarYearSelect>["years"];
|
|
24
|
+
yearFormat: ComponentProps<typeof CalendarYearSelect>["yearFormat"];
|
|
25
|
+
month: DateValue;
|
|
26
|
+
placeholder: DateValue | undefined;
|
|
27
|
+
locale: string;
|
|
28
|
+
monthIndex?: number;
|
|
29
|
+
} = $props();
|
|
30
|
+
|
|
31
|
+
function formatYear(date: DateValue) {
|
|
32
|
+
const dateObject = date.toDate(getLocalTimeZone());
|
|
33
|
+
if (typeof yearFormat === "function") return yearFormat(dateObject.getFullYear());
|
|
34
|
+
return new DateFormatter(locale, { year: yearFormat }).format(dateObject);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function formatMonth(date: DateValue) {
|
|
38
|
+
const dateObject = date.toDate(getLocalTimeZone());
|
|
39
|
+
if (typeof monthFormat === "function") return monthFormat(dateObject.getMonth() + 1);
|
|
40
|
+
return new DateFormatter(locale, { month: monthFormat }).format(dateObject);
|
|
41
|
+
}
|
|
42
|
+
</script>
|
|
43
|
+
|
|
44
|
+
{#snippet monthSelect()}
|
|
45
|
+
<CalendarMonthSelect
|
|
46
|
+
{months}
|
|
47
|
+
{monthFormat}
|
|
48
|
+
value={month.month}
|
|
49
|
+
onchange={(event) => {
|
|
50
|
+
if (placeholder === undefined) return;
|
|
51
|
+
const selectedMonth = Number.parseInt(event.currentTarget.value);
|
|
52
|
+
placeholder = placeholder.set({ month: selectedMonth }).subtract({ months: monthIndex });
|
|
53
|
+
}}
|
|
54
|
+
/>
|
|
55
|
+
{/snippet}
|
|
56
|
+
|
|
57
|
+
{#snippet yearSelect()}
|
|
58
|
+
<CalendarYearSelect {years} {yearFormat} value={month.year} />
|
|
59
|
+
{/snippet}
|
|
60
|
+
|
|
61
|
+
{#if captionLayout === "dropdown"}
|
|
62
|
+
{@render monthSelect()}
|
|
63
|
+
{@render yearSelect()}
|
|
64
|
+
{:else if captionLayout === "dropdown-months"}
|
|
65
|
+
{@render monthSelect()}
|
|
66
|
+
{#if placeholder !== undefined}{formatYear(placeholder)}{/if}
|
|
67
|
+
{:else if captionLayout === "dropdown-years"}
|
|
68
|
+
{#if placeholder !== undefined}{formatMonth(placeholder)}{/if}
|
|
69
|
+
{@render yearSelect()}
|
|
70
|
+
{:else}
|
|
71
|
+
{formatMonth(month)} {formatYear(month)}
|
|
72
|
+
{/if}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Calendar as CalendarPrimitive } from "bits-ui";
|
|
3
|
+
|
|
4
|
+
import { cn } from "@riducms/ui";
|
|
5
|
+
|
|
6
|
+
let {
|
|
7
|
+
ref = $bindable(null),
|
|
8
|
+
class: className,
|
|
9
|
+
...restProps
|
|
10
|
+
}: CalendarPrimitive.CellProps = $props();
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<CalendarPrimitive.Cell
|
|
14
|
+
bind:ref
|
|
15
|
+
class={cn(
|
|
16
|
+
"relative size-(--calendar-cell-size) p-0 text-center text-[12px] focus-within:z-20",
|
|
17
|
+
className
|
|
18
|
+
)}
|
|
19
|
+
{...restProps}
|
|
20
|
+
/>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Calendar as CalendarPrimitive } from "bits-ui";
|
|
3
|
+
|
|
4
|
+
import { buttonVariants } from "@admin/components/ui/button";
|
|
5
|
+
import { cn } from "@riducms/ui";
|
|
6
|
+
|
|
7
|
+
let {
|
|
8
|
+
ref = $bindable(null),
|
|
9
|
+
class: className,
|
|
10
|
+
...restProps
|
|
11
|
+
}: CalendarPrimitive.DayProps = $props();
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<CalendarPrimitive.Day
|
|
15
|
+
bind:ref
|
|
16
|
+
class={cn(
|
|
17
|
+
buttonVariants({ variant: "ghost", size: "icon-sm" }),
|
|
18
|
+
"size-(--calendar-cell-size) rounded-md p-0 text-[12px] font-normal text-foreground-muted",
|
|
19
|
+
"hover:bg-control-hover hover:text-foreground focus-visible:outline-2 focus-visible:outline-primary/60 focus-visible:outline-offset-0",
|
|
20
|
+
"data-[selected]:bg-primary data-[selected]:font-medium data-[selected]:text-primary-foreground data-[selected]:hover:bg-primary-hover data-[selected]:hover:text-primary-foreground",
|
|
21
|
+
"data-[today]:not-data-[selected]:bg-primary/12 data-[today]:not-data-[selected]:font-semibold data-[today]:not-data-[selected]:text-foreground",
|
|
22
|
+
"data-[outside-month]:not-data-[selected]:text-foreground-faint",
|
|
23
|
+
"data-[disabled]:pointer-events-none data-[disabled]:opacity-35 data-[unavailable]:line-through",
|
|
24
|
+
className
|
|
25
|
+
)}
|
|
26
|
+
{...restProps}
|
|
27
|
+
/>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Calendar as CalendarPrimitive } from "bits-ui";
|
|
3
|
+
|
|
4
|
+
import { cn } from "@riducms/ui";
|
|
5
|
+
|
|
6
|
+
let {
|
|
7
|
+
ref = $bindable(null),
|
|
8
|
+
class: className,
|
|
9
|
+
...restProps
|
|
10
|
+
}: CalendarPrimitive.GridRowProps = $props();
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<CalendarPrimitive.GridRow bind:ref class={cn("flex w-full", className)} {...restProps} />
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Calendar as CalendarPrimitive } from "bits-ui";
|
|
3
|
+
|
|
4
|
+
import { cn } from "@riducms/ui";
|
|
5
|
+
|
|
6
|
+
let {
|
|
7
|
+
ref = $bindable(null),
|
|
8
|
+
class: className,
|
|
9
|
+
...restProps
|
|
10
|
+
}: CalendarPrimitive.GridProps = $props();
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<CalendarPrimitive.Grid
|
|
14
|
+
bind:ref
|
|
15
|
+
class={cn("mt-3 flex w-full flex-col gap-1 border-collapse", className)}
|
|
16
|
+
{...restProps}
|
|
17
|
+
/>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Calendar as CalendarPrimitive } from "bits-ui";
|
|
3
|
+
|
|
4
|
+
import { cn } from "@riducms/ui";
|
|
5
|
+
|
|
6
|
+
let {
|
|
7
|
+
ref = $bindable(null),
|
|
8
|
+
class: className,
|
|
9
|
+
...restProps
|
|
10
|
+
}: CalendarPrimitive.HeadCellProps = $props();
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<CalendarPrimitive.HeadCell
|
|
14
|
+
bind:ref
|
|
15
|
+
class={cn(
|
|
16
|
+
"font-mono w-(--calendar-cell-size) text-center text-[9px] font-medium tracking-[0.08em] text-foreground-faint uppercase",
|
|
17
|
+
className
|
|
18
|
+
)}
|
|
19
|
+
{...restProps}
|
|
20
|
+
/>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Calendar as CalendarPrimitive } from "bits-ui";
|
|
3
|
+
|
|
4
|
+
import { cn } from "@riducms/ui";
|
|
5
|
+
|
|
6
|
+
let {
|
|
7
|
+
ref = $bindable(null),
|
|
8
|
+
class: className,
|
|
9
|
+
...restProps
|
|
10
|
+
}: CalendarPrimitive.HeaderProps = $props();
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<CalendarPrimitive.Header
|
|
14
|
+
bind:ref
|
|
15
|
+
class={cn(
|
|
16
|
+
"flex h-(--calendar-cell-size) w-full items-center justify-center gap-1.5 text-[12px] font-medium",
|
|
17
|
+
className
|
|
18
|
+
)}
|
|
19
|
+
{...restProps}
|
|
20
|
+
/>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Calendar as CalendarPrimitive } from "bits-ui";
|
|
3
|
+
|
|
4
|
+
import { cn } from "@riducms/ui";
|
|
5
|
+
|
|
6
|
+
let {
|
|
7
|
+
ref = $bindable(null),
|
|
8
|
+
class: className,
|
|
9
|
+
...restProps
|
|
10
|
+
}: CalendarPrimitive.HeadingProps = $props();
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<CalendarPrimitive.Heading
|
|
14
|
+
bind:ref
|
|
15
|
+
class={cn("px-(--calendar-cell-size) text-[12px] font-medium", className)}
|
|
16
|
+
{...restProps}
|
|
17
|
+
/>
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Calendar as CalendarPrimitive } from "bits-ui";
|
|
3
|
+
import ChevronDownIcon from "~icons/lucide/chevron-down";
|
|
4
|
+
|
|
5
|
+
import { cn, type WithoutChildrenOrChild } from "@riducms/ui";
|
|
6
|
+
|
|
7
|
+
let {
|
|
8
|
+
ref = $bindable(null),
|
|
9
|
+
class: className,
|
|
10
|
+
value,
|
|
11
|
+
onchange,
|
|
12
|
+
...restProps
|
|
13
|
+
}: WithoutChildrenOrChild<CalendarPrimitive.MonthSelectProps> = $props();
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<span
|
|
17
|
+
class={cn(
|
|
18
|
+
"relative flex rounded-md border border-control-border bg-control transition-colors focus-within:border-primary/60 focus-within:ring-2 focus-within:ring-primary/15",
|
|
19
|
+
className
|
|
20
|
+
)}
|
|
21
|
+
>
|
|
22
|
+
<CalendarPrimitive.MonthSelect bind:ref class="absolute inset-0 opacity-0" {...restProps}>
|
|
23
|
+
{#snippet child({ props, monthItems, selectedMonthItem })}
|
|
24
|
+
<select {...props} {value} {onchange} data-ridu-native-exception>
|
|
25
|
+
{#each monthItems as monthItem (monthItem.value)}
|
|
26
|
+
<option
|
|
27
|
+
value={monthItem.value}
|
|
28
|
+
selected={value === undefined
|
|
29
|
+
? monthItem.value === selectedMonthItem.value
|
|
30
|
+
: monthItem.value === value}
|
|
31
|
+
>
|
|
32
|
+
{monthItem.label}
|
|
33
|
+
</option>
|
|
34
|
+
{/each}
|
|
35
|
+
</select>
|
|
36
|
+
<span
|
|
37
|
+
class="flex h-8 items-center gap-1 ps-2 pe-1 text-[12px] font-medium text-foreground select-none"
|
|
38
|
+
aria-hidden="true"
|
|
39
|
+
>
|
|
40
|
+
{monthItems.find((item) => item.value === value)?.label ?? selectedMonthItem.label}
|
|
41
|
+
<ChevronDownIcon class="size-3 text-foreground-faint" />
|
|
42
|
+
</span>
|
|
43
|
+
{/snippet}
|
|
44
|
+
</CalendarPrimitive.MonthSelect>
|
|
45
|
+
</span>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
3
|
+
|
|
4
|
+
import { cn, type WithElementRef } from "@riducms/ui";
|
|
5
|
+
|
|
6
|
+
let {
|
|
7
|
+
ref = $bindable(null),
|
|
8
|
+
class: className,
|
|
9
|
+
children,
|
|
10
|
+
...restProps
|
|
11
|
+
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<div bind:this={ref} class={cn("flex flex-col", className)} {...restProps}>
|
|
15
|
+
{@render children?.()}
|
|
16
|
+
</div>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
3
|
+
|
|
4
|
+
import { cn, type WithElementRef } from "@riducms/ui";
|
|
5
|
+
|
|
6
|
+
let {
|
|
7
|
+
ref = $bindable(null),
|
|
8
|
+
class: className,
|
|
9
|
+
children,
|
|
10
|
+
...restProps
|
|
11
|
+
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<div
|
|
15
|
+
bind:this={ref}
|
|
16
|
+
class={cn("relative flex flex-col gap-4 md:flex-row", className)}
|
|
17
|
+
{...restProps}
|
|
18
|
+
>
|
|
19
|
+
{@render children?.()}
|
|
20
|
+
</div>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
3
|
+
|
|
4
|
+
import { cn, type WithElementRef } from "@riducms/ui";
|
|
5
|
+
|
|
6
|
+
let {
|
|
7
|
+
ref = $bindable(null),
|
|
8
|
+
class: className,
|
|
9
|
+
children,
|
|
10
|
+
...restProps
|
|
11
|
+
}: WithElementRef<HTMLAttributes<HTMLElement>> = $props();
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<nav
|
|
15
|
+
bind:this={ref}
|
|
16
|
+
class={cn("absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1", className)}
|
|
17
|
+
{...restProps}
|
|
18
|
+
>
|
|
19
|
+
{@render children?.()}
|
|
20
|
+
</nav>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Calendar as CalendarPrimitive } from "bits-ui";
|
|
3
|
+
import ChevronRightIcon from "~icons/lucide/chevron-right";
|
|
4
|
+
|
|
5
|
+
import { buttonVariants, type ButtonVariant } from "@admin/components/ui/button";
|
|
6
|
+
import { cn } from "@riducms/ui";
|
|
7
|
+
|
|
8
|
+
let {
|
|
9
|
+
ref = $bindable(null),
|
|
10
|
+
class: className,
|
|
11
|
+
children,
|
|
12
|
+
variant = "ghost",
|
|
13
|
+
...restProps
|
|
14
|
+
}: CalendarPrimitive.NextButtonProps & { variant?: ButtonVariant } = $props();
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
{#snippet fallback()}
|
|
18
|
+
<ChevronRightIcon class="size-3.5" aria-hidden="true" />
|
|
19
|
+
{/snippet}
|
|
20
|
+
|
|
21
|
+
<CalendarPrimitive.NextButton
|
|
22
|
+
bind:ref
|
|
23
|
+
class={cn(
|
|
24
|
+
buttonVariants({ variant, size: "icon-sm" }),
|
|
25
|
+
"size-(--calendar-cell-size) bg-transparent p-0 disabled:opacity-35 rtl:rotate-180",
|
|
26
|
+
className
|
|
27
|
+
)}
|
|
28
|
+
children={children ?? fallback}
|
|
29
|
+
{...restProps}
|
|
30
|
+
/>
|