@jini-ai/ui 0.4.6 → 0.4.7

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 (38) hide show
  1. package/README.md +31 -0
  2. package/dist/features/interactive-ui/interactive-ui.css +1 -1
  3. package/dist/features/interactive-ui/providers/native/data-table.js +8 -1
  4. package/dist/features/interactive-ui/providers/native/data-table.manifest.d.ts +3 -5
  5. package/dist/features/interactive-ui/providers/native/data-table.manifest.js +5 -7
  6. package/dist/features/interactive-ui/providers/recharts/bar-chart.js +8 -3
  7. package/dist/features/interactive-ui/providers/recharts/chart-config.d.ts +40 -0
  8. package/dist/features/interactive-ui/providers/recharts/chart-config.js +32 -0
  9. package/dist/features/interactive-ui/providers/recharts/chart-tokens.d.ts +18 -12
  10. package/dist/features/interactive-ui/providers/recharts/chart-tokens.js +6 -11
  11. package/dist/features/interactive-ui/providers/recharts/chart.d.ts +31 -0
  12. package/dist/features/interactive-ui/providers/recharts/chart.js +34 -0
  13. package/dist/features/interactive-ui/providers/recharts/line-chart.js +10 -3
  14. package/dist/features/interactive-ui/providers/recharts/pie-chart.js +8 -3
  15. package/dist/features/interactive-ui/providers/shadcn/data-table.d.ts +5 -1
  16. package/dist/features/interactive-ui/providers/shadcn/data-table.js +26 -2
  17. package/dist/features/interactive-ui/providers/shadcn/data-table.manifest.d.ts +8 -1
  18. package/dist/features/interactive-ui/providers/shadcn/data-table.manifest.js +6 -3
  19. package/dist/features/interactive-ui/table-data.d.ts +25 -0
  20. package/dist/features/interactive-ui/table-data.js +36 -0
  21. package/dist/features/mcp-ui/sandbox-proxy-link-forwarder.d.ts +26 -0
  22. package/dist/features/mcp-ui/sandbox-proxy-link-forwarder.js +40 -0
  23. package/dist/features/mcp-ui/sandbox-proxy.d.ts +5 -1
  24. package/dist/features/mcp-ui/sandbox-proxy.js +11 -0
  25. package/dist/features/mcp-ui/surfaces/bridge.js +6 -2
  26. package/dist/features/panel-kit/fetch-query/adapter.react.js +3 -1
  27. package/dist/features/panel-kit/fetch-query/adapter.tanstack.d.ts +11 -0
  28. package/dist/features/panel-kit/fetch-query/adapter.tanstack.js +190 -0
  29. package/dist/features/panel-kit/fetch-query/binding.react.d.ts +17 -0
  30. package/dist/features/panel-kit/fetch-query/binding.react.js +24 -0
  31. package/dist/features/panel-kit/fetch-query/cache.d.ts +2 -0
  32. package/dist/features/panel-kit/fetch-query/cache.js +2 -1
  33. package/dist/features/panel-kit/fetch-query/index.d.ts +2 -1
  34. package/dist/features/panel-kit/fetch-query/index.js +2 -1
  35. package/dist/features/panel-kit/fetch-query/tanstack.d.ts +6 -0
  36. package/dist/features/panel-kit/fetch-query/tanstack.js +4 -0
  37. package/dist/features/panel-kit/fetch-query/types.d.ts +2 -0
  38. package/package.json +16 -4
package/README.md CHANGED
@@ -487,3 +487,34 @@ Quick requests abort after 15 seconds and archive downloads after 120 seconds;
487
487
  a caller signal is combined with the timeout. Browser failures retain native abort
488
488
  reasons, including `TimeoutError`, rather than platform's `FetchTimeoutError`.
489
489
  The package no longer depends on platform. Connector examples are vendor-neutral.
490
+
491
+ ## Optional TanStack fetch-query adapter
492
+
493
+ The default `@jini-ai/ui/fetch-query` entry stays dependency-free beyond React and
494
+ the shared Jini foundation. Install the optional `@tanstack/react-query` v5 peer
495
+ to select `@jini-ai/ui/fetch-query/tanstack` at the provider composition:
496
+
497
+ ```tsx
498
+ import { FetchQueryProvider } from '@jini-ai/ui/fetch-query/tanstack';
499
+ import { useFetchQuery } from '@jini-ai/ui/fetch-query';
500
+
501
+ function Records() {
502
+ const query = useFetchQuery(
503
+ { key: ['records'], fetch: loadRecords },
504
+ { staleTime: 0, refetchOnWindowFocus: true },
505
+ );
506
+ return <span>{query.status}</span>;
507
+ }
508
+
509
+ // Existing components keep their imports; the provider binds all four hooks.
510
+ <FetchQueryProvider><Records /></FetchQueryProvider>;
511
+ ```
512
+
513
+ Both providers own isolated caches and share the same library-free types, prefix
514
+ invalidation, promise loader and mutation contracts. The default freshness is
515
+ 10 seconds, window focus refresh is off, and reads/writes do not retry failures
516
+ automatically. `refetch()` retries a failed read explicitly. Set
517
+ `refetchOnWindowFocus: true` per query to refresh stale data on focus; choose
518
+ `staleTime: 0` when every focus should revalidate. The optional `environment` port
519
+ controls offline pausing and reconnect/focus events independently per provider.
520
+ Keep the selected adapter fixed for a provider's lifetime; remount to switch it.
@@ -1,2 +1,2 @@
1
1
  /*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
2
- @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-space-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0}}}:root,[data-admin-theme],[data-color-scheme=light]{color-scheme:light;--jini-bg:var(--jini-theme-light-bg,#fff);--jini-surface:var(--jini-theme-light-surface,#f5f5f5);--jini-text:var(--jini-theme-light-text,#202020);--jini-muted:var(--jini-theme-light-muted,#666);--jini-border:var(--jini-theme-light-border,#d9d9d9);--jini-primary:var(--jini-theme-light-primary,#363636);--jini-primary-ink:var(--jini-theme-light-primary-ink,#fff);--jini-danger:var(--jini-theme-light-danger,#b42318);--jini-success:var(--jini-theme-light-success,#18763b);--jini-warning:var(--jini-theme-light-warning,#845800)}[data-color-scheme=dark]{color-scheme:dark;--jini-bg:var(--jini-theme-dark-bg,#171717);--jini-surface:var(--jini-theme-dark-surface,#242424);--jini-text:var(--jini-theme-dark-text,#f0f0f0);--jini-muted:var(--jini-theme-dark-muted,#b3b3b3);--jini-border:var(--jini-theme-dark-border,#454545);--jini-primary:var(--jini-theme-dark-primary,#e0e0e0);--jini-primary-ink:var(--jini-theme-dark-primary-ink,#202020);--jini-danger:var(--jini-theme-dark-danger,#ff8b80);--jini-success:var(--jini-theme-dark-success,#79d69b);--jini-warning:var(--jini-theme-dark-warning,#ebc36b)}:root,[data-color-scheme=light],[data-theme=light]{--jini-chart-default-1:oklch(55.29% .1129 43.4);--jini-chart-default-2:oklch(50% .11 240);--jini-chart-default-3:oklch(64% .13 88);--jini-chart-default-4:oklch(58% .15 350);--jini-chart-default-5:oklch(50% .11 155);--jini-chart-default-6:oklch(48% .12 295)}[data-color-scheme=dark],[data-theme=dark]{--jini-chart-default-1:oklch(62% .11 44);--jini-chart-default-2:oklch(64% .11 240);--jini-chart-default-3:oklch(66% .13 88);--jini-chart-default-4:oklch(65% .14 350);--jini-chart-default-5:oklch(56% .12 155);--jini-chart-default-6:oklch(64% .12 295)}:root{--jini-font-body:system-ui, sans-serif;--jini-font-heading:system-ui, sans-serif;--jini-font-mono:ui-monospace, monospace;--jini-radius:8px;--jini-density:1}:root,[data-admin-theme],[data-color-scheme]{--jini-bg-panel:var(--jini-surface);--jini-bg-subtle:var(--jini-surface)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-bg-subtle:color-mix(in srgb, var(--jini-surface) 75%, var(--jini-bg))}}:root,[data-admin-theme],[data-color-scheme]{--jini-bg-elevated:var(--jini-surface);--jini-border-soft:var(--jini-border);--jini-border-strong:var(--jini-border)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-border-strong:color-mix(in srgb, var(--jini-border) 75%, var(--jini-text))}}:root,[data-admin-theme],[data-color-scheme]{--jini-backdrop:var(--jini-text)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-backdrop:color-mix(in srgb, var(--jini-text) 42%, transparent)}}:root,[data-admin-theme],[data-color-scheme]{--jini-text-strong:var(--jini-text);--jini-text-secondary:var(--jini-text)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-text-secondary:color-mix(in srgb, var(--jini-text) 80%, var(--jini-bg))}}:root,[data-admin-theme],[data-color-scheme]{--jini-text-muted:var(--jini-muted);--jini-text-faint:var(--jini-muted)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-text-faint:color-mix(in srgb, var(--jini-muted) 75%, var(--jini-bg))}}:root,[data-admin-theme],[data-color-scheme]{--jini-text-disabled:var(--jini-muted)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-text-disabled:color-mix(in srgb, var(--jini-muted) 60%, var(--jini-bg))}}:root,[data-admin-theme],[data-color-scheme]{--jini-accent:var(--jini-primary);--jini-accent-hover:var(--jini-primary)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-accent-hover:color-mix(in srgb, var(--jini-primary) 88%, var(--jini-text))}}:root,[data-admin-theme],[data-color-scheme]{--jini-accent-strong:var(--jini-primary)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-accent-strong:color-mix(in srgb, var(--jini-primary) 85%, var(--jini-bg))}}:root,[data-admin-theme],[data-color-scheme]{--jini-accent-ink:var(--jini-primary-ink);--jini-accent-soft:var(--jini-primary)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-accent-soft:color-mix(in srgb, var(--jini-primary) 10%, transparent)}}:root,[data-admin-theme],[data-color-scheme]{--jini-accent-ring:var(--jini-primary)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-accent-ring:color-mix(in srgb, var(--jini-primary) 22%, transparent)}}:root,[data-admin-theme],[data-color-scheme]{--jini-neutral-accent:var(--jini-text);--jini-neutral-accent-hover:var(--jini-muted);--jini-neutral-accent-ink:var(--jini-bg);--jini-neutral-accent-text:var(--jini-text);--jini-neutral-accent-soft:var(--jini-text)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-neutral-accent-soft:color-mix(in srgb, var(--jini-text) 7%, transparent)}}:root,[data-admin-theme],[data-color-scheme]{--jini-neutral-accent-ring:var(--jini-text)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-neutral-accent-ring:color-mix(in srgb, var(--jini-text) 16%, transparent)}}:root,[data-admin-theme],[data-color-scheme]{--jini-link:var(--jini-primary);--jini-link-ink:var(--jini-primary-ink);--jini-success-bg:var(--jini-success)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-success-bg:color-mix(in srgb, var(--jini-success) 12%, var(--jini-bg))}}:root,[data-admin-theme],[data-color-scheme]{--jini-success-solid:var(--jini-success);--jini-success-solid-ink:var(--jini-bg);--jini-danger-bg:var(--jini-danger)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-danger-bg:color-mix(in srgb, var(--jini-danger) 12%, var(--jini-bg))}}:root,[data-admin-theme],[data-color-scheme]{--jini-warning-bg:var(--jini-warning)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-warning-bg:color-mix(in srgb, var(--jini-warning) 12%, var(--jini-bg))}}:root,[data-admin-theme],[data-color-scheme]{--jini-font-ui:var(--jini-font-body);--jini-font-display:var(--jini-font-heading);--jini-shadow-xs:0 1px 0 var(--jini-text)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-shadow-xs:0 1px 0 color-mix(in srgb, var(--jini-text) 4%, transparent)}}:root,[data-admin-theme],[data-color-scheme]{--jini-shadow-sm:0 1px 3px var(--jini-text)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-shadow-sm:0 1px 3px color-mix(in srgb, var(--jini-text) 10%, transparent)}}:root,[data-admin-theme],[data-color-scheme]{--jini-shadow-md:0 6px 24px var(--jini-text)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-shadow-md:0 6px 24px color-mix(in srgb, var(--jini-text) 15%, transparent)}}:root,[data-admin-theme],[data-color-scheme]{--jini-shadow-lg:0 24px 60px var(--jini-text)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-shadow-lg:0 24px 60px color-mix(in srgb, var(--jini-text) 22%, transparent)}}:root,[data-admin-theme],[data-color-scheme]{--jini-radius-xs:calc(var(--jini-radius) * .5);--jini-radius-sm:calc(var(--jini-radius) * .75);--jini-radius-md:calc(var(--jini-radius) * 1.25);--jini-radius-lg:calc(var(--jini-radius) * 1.5);--jini-radius-pill:999px;--jini-space-1:calc(.25rem * var(--jini-density));--jini-space-2:calc(.5rem * var(--jini-density));--jini-space-3:calc(.75rem * var(--jini-density));--jini-space-4:calc(1rem * var(--jini-density));--jini-space-5:calc(1.25rem * var(--jini-density));--jini-space-6:calc(1.5rem * var(--jini-density));--jini-space-7:calc(2rem * var(--jini-density));--jini-space-8:calc(2.5rem * var(--jini-density));--jini-font-size-2xs:.6875rem;--jini-font-size-xs:.75rem;--jini-font-size-sm:.8125rem;--jini-font-size-base:.875rem;--jini-font-size-md:.95rem;--jini-font-size-lg:1.05rem;--jini-font-size-xl:1.65rem;--jini-font-weight-normal:400;--jini-font-weight-medium:500;--jini-font-weight-semibold:600;--jini-font-weight-bold:700;--jini-line-tight:1.25;--jini-line-normal:1.5;--jini-line-relaxed:1.7;--jini-duration-fast:.12s;--jini-duration-base:.2s;--jini-duration-slow:.32s;--jini-ease-out:cubic-bezier(.23, 1, .32, 1);--jini-ease-in-out:cubic-bezier(.4, 0, .2, 1);--jini-transition-base:var(--jini-duration-base) var(--jini-ease-out);--jini-z-dropdown:100;--jini-z-sticky:200;--jini-z-overlay:300;--jini-z-modal:400;--jini-z-toast:500;--jini-modal-padding:24px;--jini-sidebar-width:240px}@layer theme{:root,:host{--font-sans:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:calc(1.5 / 1);--font-weight-medium:500;--font-weight-semibold:600;--tracking-tight:-.025em;--radius-sm:.25rem;--radius-md:.375rem;--radius-xl:.75rem;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.invisible{visibility:hidden}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.right-2{right:calc(var(--spacing) * 2)}.z-50{z-index:50}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.-mx-1{margin-inline:calc(var(--spacing) * -1)}.my-1{margin-block:var(--spacing)}.mt-4{margin-top:calc(var(--spacing) * 4)}.block{display:block}.flex{display:flex}.grid{display:grid}.inline-flex{display:inline-flex}.table{display:table}.table-caption{display:table-caption}.table-cell{display:table-cell}.table-row{display:table-row}.aspect-square{aspect-ratio:1}.h-3\.5{height:calc(var(--spacing) * 3.5)}.h-4{height:calc(var(--spacing) * 4)}.h-8{height:calc(var(--spacing) * 8)}.h-9{height:calc(var(--spacing) * 9)}.h-10{height:calc(var(--spacing) * 10)}.h-\[var\(--radix-select-trigger-height\)\]{height:var(--radix-select-trigger-height)}.h-px{height:1px}.max-h-\[--radix-select-content-available-height\]{max-height:--radix-select-content-available-height}.w-3\.5{width:calc(var(--spacing) * 3.5)}.w-4{width:calc(var(--spacing) * 4)}.w-9{width:calc(var(--spacing) * 9)}.w-full{width:100%}.min-w-\[8rem\]{min-width:8rem}.min-w-\[var\(--radix-select-trigger-width\)\]{min-width:var(--radix-select-trigger-width)}.shrink-0{flex-shrink:0}.caption-bottom{caption-side:bottom}.origin-\[--radix-select-content-transform-origin\]{transform-origin:--radix-select-content-transform-origin}.cursor-default{cursor:default}.flex-col{flex-direction:column}.place-content-center{place-content:center}.items-center{align-items:center}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-2{gap:calc(var(--spacing) * 2)}:where(.space-y-1\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1.5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1.5) * calc(1 - var(--tw-space-y-reverse)))}.overflow-x-auto{overflow-x:auto}.overflow-x-hidden{overflow-x:hidden}.overflow-y-auto{overflow-y:auto}.rounded-full{border-radius:3.40282e38px}.rounded-md{border-radius:var(--radius-md)}.rounded-sm{border-radius:var(--radius-sm)}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-input{border-color:var(--jini-border)}.border-primary{border-color:var(--jini-primary)}.bg-background{background-color:var(--jini-bg)}.bg-destructive{background-color:var(--jini-danger)}.bg-muted,.bg-muted\/50{background-color:var(--jini-surface)}@supports (color:color-mix(in lab, red, red)){.bg-muted\/50{background-color:color-mix(in oklab, var(--jini-surface) 50%, transparent)}}.bg-primary{background-color:var(--jini-primary)}.bg-secondary{background-color:var(--jini-surface)}.bg-transparent{background-color:#0000}.fill-primary{fill:var(--jini-primary)}.p-1{padding:var(--spacing)}.p-2{padding:calc(var(--spacing) * 2)}.p-6{padding:calc(var(--spacing) * 6)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-8{padding-inline:calc(var(--spacing) * 8)}.py-1{padding-block:var(--spacing)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.pt-0{padding-top:0}.pr-8{padding-right:calc(var(--spacing) * 8)}.pl-2{padding-left:calc(var(--spacing) * 2)}.text-left{text-align:left}.align-middle{vertical-align:middle}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.leading-none{--tw-leading:1;line-height:1}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.whitespace-nowrap{white-space:nowrap}.text-current{color:currentColor}.text-destructive-foreground{color:var(--jini-bg)}.text-foreground{color:var(--jini-text)}.text-input{color:var(--jini-border)}.text-muted-foreground{color:var(--jini-muted)}.text-primary{color:var(--jini-primary)}.text-primary-foreground{color:var(--jini-primary-ink)}.text-secondary-foreground{color:var(--jini-text)}.underline-offset-4{text-underline-offset:4px}.opacity-50{opacity:.5}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a), 0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-offset-background{--tw-ring-offset-color:var(--jini-bg)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}.peer-disabled\:cursor-not-allowed:is(:where(.peer):disabled~*){cursor:not-allowed}.peer-disabled\:opacity-70:is(:where(.peer):disabled~*){opacity:.7}.file\:border-0::file-selector-button{border-style:var(--tw-border-style);border-width:0}.file\:bg-transparent::file-selector-button{background-color:#0000}.file\:text-sm::file-selector-button{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.file\:font-medium::file-selector-button{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.file\:text-foreground::file-selector-button{color:var(--jini-text)}.placeholder\:text-muted-foreground::placeholder{color:var(--jini-muted)}@media (hover:hover){.hover\:bg-accent:hover{background-color:var(--jini-surface)}.hover\:bg-destructive\/90:hover{background-color:var(--jini-danger)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-destructive\/90:hover{background-color:color-mix(in oklab, var(--jini-danger) 90%, transparent)}}.hover\:bg-muted\/50:hover{background-color:var(--jini-surface)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-muted\/50:hover{background-color:color-mix(in oklab, var(--jini-surface) 50%, transparent)}}.hover\:bg-primary\/90:hover{background-color:var(--jini-primary)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-primary\/90:hover{background-color:color-mix(in oklab, var(--jini-primary) 90%, transparent)}}.hover\:bg-secondary\/80:hover{background-color:var(--jini-surface)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-secondary\/80:hover{background-color:color-mix(in oklab, var(--jini-surface) 80%, transparent)}}.hover\:text-accent-foreground:hover{color:var(--jini-text)}.hover\:underline:hover{text-decoration-line:underline}}.focus\:bg-accent:focus{background-color:var(--jini-surface)}.focus\:text-accent-foreground:focus{color:var(--jini-text)}.focus\:ring-1:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus\:ring-ring:focus{--tw-ring-color:var(--jini-primary)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.focus-visible\:ring-1:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus-visible\:ring-ring:focus-visible{--tw-ring-color:var(--jini-primary)}.focus-visible\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}.has-aria-expanded\:bg-muted\/50:has([aria-expanded=true]){background-color:var(--jini-surface)}@supports (color:color-mix(in lab, red, red)){.has-aria-expanded\:bg-muted\/50:has([aria-expanded=true]){background-color:color-mix(in oklab, var(--jini-surface) 50%, transparent)}}.data-\[disabled\]\:pointer-events-none[data-disabled]{pointer-events:none}.data-\[disabled\]\:opacity-50[data-disabled]{opacity:.5}.data-\[placeholder\]\:text-muted-foreground[data-placeholder]{color:var(--jini-muted)}.data-\[side\=bottom\]\:translate-y-1[data-side=bottom]{--tw-translate-y:var(--spacing);translate:var(--tw-translate-x) var(--tw-translate-y)}.data-\[side\=left\]\:-translate-x-1[data-side=left]{--tw-translate-x:calc(var(--spacing) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.data-\[side\=right\]\:translate-x-1[data-side=right]{--tw-translate-x:var(--spacing);translate:var(--tw-translate-x) var(--tw-translate-y)}.data-\[side\=top\]\:-translate-y-1[data-side=top]{--tw-translate-y:calc(var(--spacing) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.data-\[state\=checked\]\:bg-primary[data-state=checked]{background-color:var(--jini-primary)}.data-\[state\=checked\]\:text-primary-foreground[data-state=checked]{color:var(--jini-primary-ink)}.data-\[state\=selected\]\:bg-muted[data-state=selected]{background-color:var(--jini-surface)}@media (min-width:48rem){.md\:text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}}.\[\&_svg\]\:pointer-events-none svg{pointer-events:none}.\[\&_svg\]\:size-4 svg{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.\[\&_svg\]\:shrink-0 svg{flex-shrink:0}.\[\&_tr\]\:border-b tr{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.\[\&_tr\:last-child\]\:border-0 tr:last-child{border-style:var(--tw-border-style);border-width:0}.\[\&\:has\(\[role\=checkbox\]\)\]\:pr-0:has([role=checkbox]){padding-right:0}.\[\&\>span\]\:line-clamp-1>span{-webkit-line-clamp:1;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.\[\&\>tr\]\:last\:border-b-0>tr:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0}}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}
2
+ @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-space-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0}}}:root,[data-admin-theme],[data-color-scheme=light]{color-scheme:light;--jini-bg:var(--jini-theme-light-bg,#fff);--jini-surface:var(--jini-theme-light-surface,#f5f5f5);--jini-text:var(--jini-theme-light-text,#202020);--jini-muted:var(--jini-theme-light-muted,#666);--jini-border:var(--jini-theme-light-border,#d9d9d9);--jini-primary:var(--jini-theme-light-primary,#363636);--jini-primary-ink:var(--jini-theme-light-primary-ink,#fff);--jini-danger:var(--jini-theme-light-danger,#b42318);--jini-success:var(--jini-theme-light-success,#18763b);--jini-warning:var(--jini-theme-light-warning,#845800)}[data-color-scheme=dark]{color-scheme:dark;--jini-bg:var(--jini-theme-dark-bg,#171717);--jini-surface:var(--jini-theme-dark-surface,#242424);--jini-text:var(--jini-theme-dark-text,#f0f0f0);--jini-muted:var(--jini-theme-dark-muted,#b3b3b3);--jini-border:var(--jini-theme-dark-border,#454545);--jini-primary:var(--jini-theme-dark-primary,#e0e0e0);--jini-primary-ink:var(--jini-theme-dark-primary-ink,#202020);--jini-danger:var(--jini-theme-dark-danger,#ff8b80);--jini-success:var(--jini-theme-dark-success,#79d69b);--jini-warning:var(--jini-theme-dark-warning,#ebc36b)}:root,[data-color-scheme=light],[data-theme=light]{--jini-chart-default-1:oklch(55.29% .1129 43.4);--jini-chart-default-2:oklch(50% .11 240);--jini-chart-default-3:oklch(64% .13 88);--jini-chart-default-4:oklch(58% .15 350);--jini-chart-default-5:oklch(50% .11 155);--jini-chart-default-6:oklch(48% .12 295)}[data-color-scheme=dark],[data-theme=dark]{--jini-chart-default-1:oklch(62% .11 44);--jini-chart-default-2:oklch(64% .11 240);--jini-chart-default-3:oklch(66% .13 88);--jini-chart-default-4:oklch(65% .14 350);--jini-chart-default-5:oklch(56% .12 155);--jini-chart-default-6:oklch(64% .12 295)}:root{--jini-font-body:system-ui, sans-serif;--jini-font-heading:system-ui, sans-serif;--jini-font-mono:ui-monospace, monospace;--jini-radius:8px;--jini-density:1}:root,[data-admin-theme],[data-color-scheme]{--jini-bg-panel:var(--jini-surface);--jini-bg-subtle:var(--jini-surface)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-bg-subtle:color-mix(in srgb, var(--jini-surface) 75%, var(--jini-bg))}}:root,[data-admin-theme],[data-color-scheme]{--jini-bg-elevated:var(--jini-surface);--jini-border-soft:var(--jini-border);--jini-border-strong:var(--jini-border)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-border-strong:color-mix(in srgb, var(--jini-border) 75%, var(--jini-text))}}:root,[data-admin-theme],[data-color-scheme]{--jini-backdrop:var(--jini-text)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-backdrop:color-mix(in srgb, var(--jini-text) 42%, transparent)}}:root,[data-admin-theme],[data-color-scheme]{--jini-text-strong:var(--jini-text);--jini-text-secondary:var(--jini-text)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-text-secondary:color-mix(in srgb, var(--jini-text) 80%, var(--jini-bg))}}:root,[data-admin-theme],[data-color-scheme]{--jini-text-muted:var(--jini-muted);--jini-text-faint:var(--jini-muted)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-text-faint:color-mix(in srgb, var(--jini-muted) 75%, var(--jini-bg))}}:root,[data-admin-theme],[data-color-scheme]{--jini-text-disabled:var(--jini-muted)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-text-disabled:color-mix(in srgb, var(--jini-muted) 60%, var(--jini-bg))}}:root,[data-admin-theme],[data-color-scheme]{--jini-accent:var(--jini-primary);--jini-accent-hover:var(--jini-primary)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-accent-hover:color-mix(in srgb, var(--jini-primary) 88%, var(--jini-text))}}:root,[data-admin-theme],[data-color-scheme]{--jini-accent-strong:var(--jini-primary)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-accent-strong:color-mix(in srgb, var(--jini-primary) 85%, var(--jini-bg))}}:root,[data-admin-theme],[data-color-scheme]{--jini-accent-ink:var(--jini-primary-ink);--jini-accent-soft:var(--jini-primary)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-accent-soft:color-mix(in srgb, var(--jini-primary) 10%, transparent)}}:root,[data-admin-theme],[data-color-scheme]{--jini-accent-ring:var(--jini-primary)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-accent-ring:color-mix(in srgb, var(--jini-primary) 22%, transparent)}}:root,[data-admin-theme],[data-color-scheme]{--jini-neutral-accent:var(--jini-text);--jini-neutral-accent-hover:var(--jini-muted);--jini-neutral-accent-ink:var(--jini-bg);--jini-neutral-accent-text:var(--jini-text);--jini-neutral-accent-soft:var(--jini-text)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-neutral-accent-soft:color-mix(in srgb, var(--jini-text) 7%, transparent)}}:root,[data-admin-theme],[data-color-scheme]{--jini-neutral-accent-ring:var(--jini-text)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-neutral-accent-ring:color-mix(in srgb, var(--jini-text) 16%, transparent)}}:root,[data-admin-theme],[data-color-scheme]{--jini-link:var(--jini-primary);--jini-link-ink:var(--jini-primary-ink);--jini-success-bg:var(--jini-success)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-success-bg:color-mix(in srgb, var(--jini-success) 12%, var(--jini-bg))}}:root,[data-admin-theme],[data-color-scheme]{--jini-success-solid:var(--jini-success);--jini-success-solid-ink:var(--jini-bg);--jini-danger-bg:var(--jini-danger)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-danger-bg:color-mix(in srgb, var(--jini-danger) 12%, var(--jini-bg))}}:root,[data-admin-theme],[data-color-scheme]{--jini-warning-bg:var(--jini-warning)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-warning-bg:color-mix(in srgb, var(--jini-warning) 12%, var(--jini-bg))}}:root,[data-admin-theme],[data-color-scheme]{--jini-font-ui:var(--jini-font-body);--jini-font-display:var(--jini-font-heading);--jini-shadow-xs:0 1px 0 var(--jini-text)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-shadow-xs:0 1px 0 color-mix(in srgb, var(--jini-text) 4%, transparent)}}:root,[data-admin-theme],[data-color-scheme]{--jini-shadow-sm:0 1px 3px var(--jini-text)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-shadow-sm:0 1px 3px color-mix(in srgb, var(--jini-text) 10%, transparent)}}:root,[data-admin-theme],[data-color-scheme]{--jini-shadow-md:0 6px 24px var(--jini-text)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-shadow-md:0 6px 24px color-mix(in srgb, var(--jini-text) 15%, transparent)}}:root,[data-admin-theme],[data-color-scheme]{--jini-shadow-lg:0 24px 60px var(--jini-text)}@supports (color:color-mix(in lab, red, red)){:root,[data-admin-theme],[data-color-scheme]{--jini-shadow-lg:0 24px 60px color-mix(in srgb, var(--jini-text) 22%, transparent)}}:root,[data-admin-theme],[data-color-scheme]{--jini-radius-xs:calc(var(--jini-radius) * .5);--jini-radius-sm:calc(var(--jini-radius) * .75);--jini-radius-md:calc(var(--jini-radius) * 1.25);--jini-radius-lg:calc(var(--jini-radius) * 1.5);--jini-radius-pill:999px;--jini-space-1:calc(.25rem * var(--jini-density));--jini-space-2:calc(.5rem * var(--jini-density));--jini-space-3:calc(.75rem * var(--jini-density));--jini-space-4:calc(1rem * var(--jini-density));--jini-space-5:calc(1.25rem * var(--jini-density));--jini-space-6:calc(1.5rem * var(--jini-density));--jini-space-7:calc(2rem * var(--jini-density));--jini-space-8:calc(2.5rem * var(--jini-density));--jini-font-size-2xs:.6875rem;--jini-font-size-xs:.75rem;--jini-font-size-sm:.8125rem;--jini-font-size-base:.875rem;--jini-font-size-md:.95rem;--jini-font-size-lg:1.05rem;--jini-font-size-xl:1.65rem;--jini-font-weight-normal:400;--jini-font-weight-medium:500;--jini-font-weight-semibold:600;--jini-font-weight-bold:700;--jini-line-tight:1.25;--jini-line-normal:1.5;--jini-line-relaxed:1.7;--jini-duration-fast:.12s;--jini-duration-base:.2s;--jini-duration-slow:.32s;--jini-ease-out:cubic-bezier(.23, 1, .32, 1);--jini-ease-in-out:cubic-bezier(.4, 0, .2, 1);--jini-transition-base:var(--jini-duration-base) var(--jini-ease-out);--jini-z-dropdown:100;--jini-z-sticky:200;--jini-z-overlay:300;--jini-z-modal:400;--jini-z-toast:500;--jini-modal-padding:24px;--jini-sidebar-width:240px}@layer theme{:root,:host{--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:calc(1.5 / 1);--font-weight-medium:500;--font-weight-semibold:600;--tracking-tight:-.025em;--radius-sm:.25rem;--radius-md:.375rem;--radius-xl:.75rem;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1)}}@layer base,components;@layer utilities{.invisible{visibility:hidden}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.sticky{position:sticky}.right-2{right:calc(var(--spacing) * 2)}.z-50{z-index:50}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.-mx-1{margin-inline:calc(var(--spacing) * -1)}.my-1{margin-block:var(--spacing)}.mt-4{margin-top:calc(var(--spacing) * 4)}.block{display:block}.flex{display:flex}.grid{display:grid}.inline-flex{display:inline-flex}.table{display:table}.table-caption{display:table-caption}.table-cell{display:table-cell}.table-row{display:table-row}.aspect-square{aspect-ratio:1}.h-3\.5{height:calc(var(--spacing) * 3.5)}.h-4{height:calc(var(--spacing) * 4)}.h-8{height:calc(var(--spacing) * 8)}.h-9{height:calc(var(--spacing) * 9)}.h-10{height:calc(var(--spacing) * 10)}.h-\[var\(--radix-select-trigger-height\)\]{height:var(--radix-select-trigger-height)}.h-px{height:1px}.max-h-\[--radix-select-content-available-height\]{max-height:--radix-select-content-available-height}.w-3\.5{width:calc(var(--spacing) * 3.5)}.w-4{width:calc(var(--spacing) * 4)}.w-9{width:calc(var(--spacing) * 9)}.w-full{width:100%}.min-w-\[8rem\]{min-width:8rem}.min-w-\[var\(--radix-select-trigger-width\)\]{min-width:var(--radix-select-trigger-width)}.shrink-0{flex-shrink:0}.caption-bottom{caption-side:bottom}.origin-\[--radix-select-content-transform-origin\]{transform-origin:--radix-select-content-transform-origin}.cursor-default{cursor:default}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.place-content-center{place-content:center}.items-center{align-items:center}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-2{gap:calc(var(--spacing) * 2)}:where(.space-y-1\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1.5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1.5) * calc(1 - var(--tw-space-y-reverse)))}.overflow-x-auto{overflow-x:auto}.overflow-x-hidden{overflow-x:hidden}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:var(--jini-radius)}.rounded-full{border-radius:3.40282e38px}.rounded-md{border-radius:var(--radius-md)}.rounded-sm{border-radius:var(--radius-sm)}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-input{border-color:var(--jini-border)}.border-primary{border-color:var(--jini-primary)}.bg-background{background-color:var(--jini-bg)}.bg-destructive{background-color:var(--jini-danger)}.bg-muted,.bg-muted\/50{background-color:var(--jini-surface)}@supports (color:color-mix(in lab, red, red)){.bg-muted\/50{background-color:color-mix(in oklab, var(--jini-surface) 50%, transparent)}}.bg-primary{background-color:var(--jini-primary)}.bg-secondary{background-color:var(--jini-surface)}.bg-transparent{background-color:#0000}.fill-primary{fill:var(--jini-primary)}.p-1{padding:var(--spacing)}.p-2{padding:calc(var(--spacing) * 2)}.p-6{padding:calc(var(--spacing) * 6)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-8{padding-inline:calc(var(--spacing) * 8)}.py-1{padding-block:var(--spacing)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.pt-0{padding-top:0}.pr-8{padding-right:calc(var(--spacing) * 8)}.pl-2{padding-left:calc(var(--spacing) * 2)}.text-left{text-align:left}.align-middle{vertical-align:middle}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.leading-none{--tw-leading:1;line-height:1}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.whitespace-nowrap{white-space:nowrap}.text-current{color:currentColor}.text-destructive-foreground{color:var(--jini-bg)}.text-foreground{color:var(--jini-text)}.text-input{color:var(--jini-border)}.text-muted-foreground{color:var(--jini-muted)}.text-primary{color:var(--jini-primary)}.text-primary-foreground{color:var(--jini-primary-ink)}.text-secondary-foreground{color:var(--jini-text)}.underline-offset-4{text-underline-offset:4px}.opacity-50{opacity:.5}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a), 0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-offset-background{--tw-ring-offset-color:var(--jini-bg)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}.peer-disabled\:cursor-not-allowed:is(:where(.peer):disabled~*){cursor:not-allowed}.peer-disabled\:opacity-70:is(:where(.peer):disabled~*){opacity:.7}.file\:border-0::file-selector-button{border-style:var(--tw-border-style);border-width:0}.file\:bg-transparent::file-selector-button{background-color:#0000}.file\:text-sm::file-selector-button{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.file\:font-medium::file-selector-button{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.file\:text-foreground::file-selector-button{color:var(--jini-text)}.placeholder\:text-muted-foreground::placeholder{color:var(--jini-muted)}@media (hover:hover){.hover\:bg-accent:hover{background-color:var(--jini-surface)}.hover\:bg-destructive\/90:hover{background-color:var(--jini-danger)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-destructive\/90:hover{background-color:color-mix(in oklab, var(--jini-danger) 90%, transparent)}}.hover\:bg-muted\/50:hover{background-color:var(--jini-surface)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-muted\/50:hover{background-color:color-mix(in oklab, var(--jini-surface) 50%, transparent)}}.hover\:bg-primary\/90:hover{background-color:var(--jini-primary)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-primary\/90:hover{background-color:color-mix(in oklab, var(--jini-primary) 90%, transparent)}}.hover\:bg-secondary\/80:hover{background-color:var(--jini-surface)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-secondary\/80:hover{background-color:color-mix(in oklab, var(--jini-surface) 80%, transparent)}}.hover\:text-accent-foreground:hover{color:var(--jini-text)}.hover\:underline:hover{text-decoration-line:underline}}.focus\:bg-accent:focus{background-color:var(--jini-surface)}.focus\:text-accent-foreground:focus{color:var(--jini-text)}.focus\:ring-1:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus\:ring-ring:focus{--tw-ring-color:var(--jini-primary)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.focus-visible\:ring-1:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus-visible\:ring-ring:focus-visible{--tw-ring-color:var(--jini-primary)}.focus-visible\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}.has-aria-expanded\:bg-muted\/50:has([aria-expanded=true]){background-color:var(--jini-surface)}@supports (color:color-mix(in lab, red, red)){.has-aria-expanded\:bg-muted\/50:has([aria-expanded=true]){background-color:color-mix(in oklab, var(--jini-surface) 50%, transparent)}}.data-\[disabled\]\:pointer-events-none[data-disabled]{pointer-events:none}.data-\[disabled\]\:opacity-50[data-disabled]{opacity:.5}.data-\[placeholder\]\:text-muted-foreground[data-placeholder]{color:var(--jini-muted)}.data-\[side\=bottom\]\:translate-y-1[data-side=bottom]{--tw-translate-y:var(--spacing);translate:var(--tw-translate-x) var(--tw-translate-y)}.data-\[side\=left\]\:-translate-x-1[data-side=left]{--tw-translate-x:calc(var(--spacing) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.data-\[side\=right\]\:translate-x-1[data-side=right]{--tw-translate-x:var(--spacing);translate:var(--tw-translate-x) var(--tw-translate-y)}.data-\[side\=top\]\:-translate-y-1[data-side=top]{--tw-translate-y:calc(var(--spacing) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.data-\[state\=checked\]\:bg-primary[data-state=checked]{background-color:var(--jini-primary)}.data-\[state\=checked\]\:text-primary-foreground[data-state=checked]{color:var(--jini-primary-ink)}.data-\[state\=selected\]\:bg-muted[data-state=selected]{background-color:var(--jini-surface)}@media (min-width:48rem){.md\:text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}}.\[\&_svg\]\:pointer-events-none svg{pointer-events:none}.\[\&_svg\]\:size-4 svg{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.\[\&_svg\]\:shrink-0 svg{flex-shrink:0}.\[\&_tr\]\:border-b tr{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.\[\&_tr\:last-child\]\:border-0 tr:last-child{border-style:var(--tw-border-style);border-width:0}.\[\&\:has\(\[role\=checkbox\]\)\]\:pr-0:has([role=checkbox]){padding-right:0}.\[\&\>span\]\:line-clamp-1>span{-webkit-line-clamp:1;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.\[\&\>tr\]\:last\:border-b-0>tr:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0}}.jini-data-table-frame{border:1px solid var(--jini-border);border-radius:var(--jini-radius);background:var(--jini-bg);min-width:0;max-width:100%;color:var(--jini-text);overflow:hidden}.jini-data-table-scroll,.jini-data-table-frame>[data-slot=table-container]{overscroll-behavior-x:contain;width:100%;max-height:28rem;overflow:auto}.jini-data-table{border-collapse:separate;border-spacing:0;width:100%;font-family:var(--jini-font-body);font-size:var(--jini-font-size-sm);line-height:var(--jini-line-normal);font-variant-numeric:tabular-nums}.jini-data-table th,.jini-data-table td{text-align:left;vertical-align:middle;white-space:nowrap;border-bottom:1px solid var(--jini-border);height:2.5rem;padding:.625rem .875rem}.jini-data-table th{z-index:1;background:var(--jini-surface);color:var(--jini-muted);font-size:var(--jini-font-size-xs);font-weight:var(--jini-font-weight-semibold);position:sticky;top:0}.jini-data-table tbody tr:last-child td{border-bottom:0}.jini-data-table tbody tr:nth-child(2n){background:var(--jini-bg-subtle)}.jini-data-table tbody tr:hover,.jini-data-table tbody tr:focus-visible{background:var(--jini-surface)}.jini-data-table tbody tr[role=button]{cursor:pointer}.jini-data-table [data-numeric=true]{text-align:right}.jini-data-table-sort{width:100%;min-height:1.5rem;color:inherit;font:inherit;text-align:inherit;cursor:pointer;background:0 0;border:0;justify-content:space-between;align-items:center;gap:.625rem;padding:0;display:inline-flex}.jini-data-table [data-numeric=true] .jini-data-table-sort{justify-content:flex-end}.jini-data-table th[aria-sort=ascending],.jini-data-table th[aria-sort=descending],.jini-data-table-sort:hover{color:var(--jini-text)}.jini-data-table td.jini-data-table-empty{height:8rem;color:var(--jini-muted);text-align:center}.jini-data-table-pagination{border-top:1px solid var(--jini-border);color:var(--jini-muted);font-size:var(--jini-font-size-xs);font-variant-numeric:tabular-nums;flex-wrap:wrap;justify-content:space-between;align-items:center;gap:.75rem;padding:.625rem .875rem;display:flex}.jini-data-table-pagination-controls{gap:.5rem;display:flex}.jini-data-table-pagination button{border:1px solid var(--jini-border);border-radius:var(--jini-radius-sm);background:var(--jini-bg);min-height:2rem;color:var(--jini-text);font:inherit;cursor:pointer;padding:.375rem .75rem}.jini-data-table-pagination button:hover:not(:disabled){background:var(--jini-surface)}.jini-data-table-pagination button:disabled{opacity:.5;cursor:default}.jini-data-table-sort:focus-visible,.jini-data-table-pagination button:focus-visible,.jini-data-table tr[role=button]:focus-visible{outline:2px solid var(--jini-primary);outline-offset:-2px}.jini-chart{width:100%;min-width:0;color:var(--jini-chart-text,var(--jini-text));font-family:var(--jini-font-body);margin:0;font-size:.75rem}.jini-chart-caption{clip-path:inset(50%);white-space:nowrap;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.jini-chart .recharts-surface:focus-visible{outline:2px solid var(--jini-chart-1,var(--jini-chart-default-1));outline-offset:3px;border-radius:var(--jini-radius-sm)}.jini-chart-tooltip{border:1px solid var(--jini-chart-grid,var(--jini-border));border-radius:var(--jini-radius-sm);background:var(--jini-chart-surface,var(--jini-bg));min-width:9rem;max-width:min(22rem,80vw);color:var(--jini-chart-text,var(--jini-text));box-shadow:var(--jini-shadow-md);padding:.625rem .75rem;font-size:.75rem;line-height:1.5}.jini-chart-tooltip-label{overflow-wrap:anywhere;margin-bottom:.375rem;font-weight:600}.jini-chart-tooltip-items{gap:.375rem;display:grid}.jini-chart-tooltip-item{align-items:center;gap:.5rem;display:flex}.jini-chart-swatch{border-radius:2px;flex:none;width:.5rem;height:.5rem;display:inline-block}.jini-chart-tooltip-name{color:var(--jini-chart-axis,var(--jini-muted));overflow-wrap:anywhere;flex:1}.jini-chart-tooltip-value,.jini-chart-legend-value{font-variant-numeric:tabular-nums;font-weight:600}.jini-chart-legend{color:var(--jini-chart-axis,var(--jini-muted));flex-wrap:wrap;justify-content:center;gap:.5rem 1rem;margin:.5rem 0 0;padding:0;line-height:1.5;list-style:none;display:flex}.jini-chart-legend-item{overflow-wrap:anywhere;align-items:center;gap:.375rem;min-width:0;max-width:100%;display:inline-flex}.jini-chart-legend-item>span:not(.jini-chart-swatch){min-width:0}.jini-chart-legend-value{color:var(--jini-chart-text,var(--jini-text))}.jini-chart-total{fill:var(--jini-chart-text,var(--jini-text));font-variant-numeric:tabular-nums;letter-spacing:-.04em;pointer-events:none;font-size:1.75rem;font-weight:600}.jini-chart-total-label{fill:var(--jini-chart-axis,var(--jini-muted));letter-spacing:normal;font-size:.75rem;font-weight:400}@media (prefers-reduced-motion:reduce){.jini-chart *,.jini-chart :before,.jini-chart :after{transition:none!important;animation:none!important}}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}
@@ -1,5 +1,12 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { getNumericColumnKeys } from '../../table-data.js';
2
3
  export function DataTable({ columns, rows, onRowClick }) {
3
- return (_jsxs("table", { children: [_jsx("thead", { children: _jsx("tr", { children: columns.map((column) => (_jsx("th", { children: column.label }, column.key))) }) }), _jsx("tbody", { children: rows.map((row, index) => (_jsx("tr", { onClick: onRowClick ? () => onRowClick(row, index) : undefined, role: onRowClick ? 'button' : undefined, children: columns.map((column) => (_jsx("td", { children: String(row[column.key] ?? '') }, column.key))) }, index))) })] }));
4
+ const numericKeys = getNumericColumnKeys({ columns, rows });
5
+ return (_jsx("div", { className: "jini-data-table-frame", "data-table-provider": "native", children: _jsx("div", { className: "jini-data-table-scroll", children: _jsxs("table", { className: "jini-data-table", children: [_jsx("thead", { children: _jsx("tr", { children: columns.map((column) => (_jsx("th", { scope: "col", "data-numeric": numericKeys.has(column.key), children: column.label }, column.key))) }) }), _jsxs("tbody", { children: [rows.length === 0 && _jsx("tr", { children: _jsx("td", { className: "jini-data-table-empty", colSpan: columns.length, children: "No results." }) }), rows.map((row, index) => (_jsx("tr", { onClick: onRowClick ? () => onRowClick(row, index) : undefined, role: onRowClick ? 'button' : undefined, tabIndex: onRowClick ? 0 : undefined, onKeyDown: onRowClick ? (event) => {
6
+ if (event.target === event.currentTarget && (event.key === 'Enter' || event.key === ' ')) {
7
+ event.preventDefault();
8
+ onRowClick(row, index);
9
+ }
10
+ } : undefined, children: columns.map((column) => (_jsx("td", { "data-numeric": numericKeys.has(column.key), children: String(row[column.key] ?? '') }, column.key))) }, index)))] })] }) }) }));
4
11
  }
5
12
  //# sourceMappingURL=data-table.js.map
@@ -1,11 +1,9 @@
1
1
  import { z } from 'zod';
2
2
  import type { InteractiveComponentManifest } from '../../types.js';
3
3
  /**
4
- * Zero-React reference provider: no external component library wired in yet (`ui/package.json`
5
- * has no shadcn/radix dependency — adding one is a separate decision, not implied by this
6
- * scaffold). Proves the manifest/implementation split with something real and testable rather
7
- * than a stub. A `shadcn`/`21st`/`magic` sibling folder under `providers/` replaces this as the
8
- * default resolution once those adapters exist; `native` stays as the dependency-free fallback.
4
+ * Zero-React manifest for the dependency-free HTML fallback. shadcn now owns preferred table
5
+ * resolution; native stays available without external component primitives. Both providers
6
+ * share the table presentation stylesheet, so fallback does not mean raw browser markup.
9
7
  */
10
8
  /**
11
9
  * `.passthrough()`, not `.strict()` — an A2UI-embedded instance of this component may carry an
@@ -1,10 +1,8 @@
1
1
  import { z } from 'zod';
2
2
  /**
3
- * Zero-React reference provider: no external component library wired in yet (`ui/package.json`
4
- * has no shadcn/radix dependency — adding one is a separate decision, not implied by this
5
- * scaffold). Proves the manifest/implementation split with something real and testable rather
6
- * than a stub. A `shadcn`/`21st`/`magic` sibling folder under `providers/` replaces this as the
7
- * default resolution once those adapters exist; `native` stays as the dependency-free fallback.
3
+ * Zero-React manifest for the dependency-free HTML fallback. shadcn now owns preferred table
4
+ * resolution; native stays available without external component primitives. Both providers
5
+ * share the table presentation stylesheet, so fallback does not mean raw browser markup.
8
6
  */
9
7
  /**
10
8
  * `.passthrough()`, not `.strict()` — an A2UI-embedded instance of this component may carry an
@@ -24,8 +22,8 @@ export const nativeDataTablePropsSchema = z
24
22
  export const nativeDataTableManifest = {
25
23
  id: 'native.data-table',
26
24
  provider: 'native',
27
- capabilities: ['data-table', 'table', 'tabular-data'],
25
+ capabilities: ['data-table', 'table', 'tabular-data', 'spreadsheet', 'list-of-records'],
28
26
  propsSchema: nativeDataTablePropsSchema,
29
- description: 'Plain HTML table: columns + rows, optional row click. No external UI library.',
27
+ description: 'Styled HTML table fallback for tabular data, spreadsheets and lists of records: columns + rows, optional row click. Borders, row separators, padded cells, muted left-aligned headers, hover and horizontal scroll. No sorting or paging; prefer shadcn.data-table for the full table experience. Load @jini-ai/ui/interactive-ui.css in the renderer host.',
30
28
  };
31
29
  //# sourceMappingURL=data-table.manifest.js.map
@@ -1,7 +1,12 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Bar, BarChart as RechartsBarChart, CartesianGrid, ResponsiveContainer, Tooltip, XAxis, YAxis } from 'recharts';
3
- import { CHART_AXIS_TICK, CHART_CURSOR, CHART_GRID_STROKE, CHART_PRIMARY_COLOR, CHART_TOOLTIP_CONTENT_STYLE, CHART_TOOLTIP_TEXT_STYLE } from './chart-tokens.js';
2
+ import { Bar, BarChart as RechartsBarChart, CartesianGrid, Tooltip, XAxis, YAxis } from 'recharts';
3
+ import { CHART_AXIS_PROPS, CHART_CURSOR, CHART_GRID_STROKE, CHART_PRIMARY_COLOR } from './chart-tokens.js';
4
+ import { chartTickFormatter, createChartConfig } from './chart-config.js';
5
+ import { ChartContainer, ChartTooltipContent } from './chart.js';
4
6
  export function BarChart({ data, categoryKey, valueKey, color = CHART_PRIMARY_COLOR }) {
5
- return (_jsx(ResponsiveContainer, { width: "100%", height: 300, children: _jsxs(RechartsBarChart, { data: data, children: [_jsx(CartesianGrid, { strokeDasharray: "3 3", stroke: CHART_GRID_STROKE, vertical: false }), _jsx(XAxis, { dataKey: categoryKey, interval: 0, tick: CHART_AXIS_TICK, stroke: CHART_GRID_STROKE, tickLine: false }), _jsx(YAxis, { tick: CHART_AXIS_TICK, stroke: CHART_GRID_STROKE, tickLine: false, axisLine: false }), _jsx(Tooltip, { cursor: CHART_CURSOR, contentStyle: CHART_TOOLTIP_CONTENT_STYLE, labelStyle: CHART_TOOLTIP_TEXT_STYLE, itemStyle: CHART_TOOLTIP_TEXT_STYLE }), _jsx(Bar, { dataKey: valueKey, fill: color, radius: [4, 4, 0, 0], maxBarSize: 64, isAnimationActive: false })] }) }));
7
+ const config = createChartConfig({ series: [{ key: valueKey, label: valueKey }] }, { color });
8
+ const title = `${valueKey} by ${categoryKey}`;
9
+ const description = `Bar chart with ${data.length} categories. Use arrow keys to explore values.`;
10
+ return (_jsx(ChartContainer, { config: config, title: title, description: description, children: _jsxs(RechartsBarChart, { data: data, accessibilityLayer: true, title: title, desc: description, margin: { top: 16, right: 12, bottom: 8, left: 0 }, barCategoryGap: "24%", children: [_jsx(CartesianGrid, { strokeDasharray: "3 3", stroke: CHART_GRID_STROKE, strokeOpacity: 0.6, vertical: false }), _jsx(XAxis, { dataKey: categoryKey, interval: 0, ...CHART_AXIS_PROPS }), _jsx(YAxis, { ...CHART_AXIS_PROPS, tickFormatter: chartTickFormatter, width: 48 }), _jsx(Tooltip, { cursor: CHART_CURSOR, content: _jsx(ChartTooltipContent, {}), isAnimationActive: false }), _jsx(Bar, { dataKey: valueKey, fill: config[valueKey].color, radius: [6, 6, 0, 0], maxBarSize: 40, isAnimationActive: false })] }) }));
6
11
  }
7
12
  //# sourceMappingURL=bar-chart.js.map
@@ -0,0 +1,40 @@
1
+ export interface ChartSeries {
2
+ readonly label: string;
3
+ readonly color: string;
4
+ readonly value?: number;
5
+ }
6
+ /** Provider-local configuration shared by marks, tooltip swatches and the legend. */
7
+ export type ChartConfig = Readonly<Record<string, ChartSeries>>;
8
+ interface SeriesInput {
9
+ readonly key: string;
10
+ readonly label: string;
11
+ readonly value?: number;
12
+ }
13
+ /**
14
+ * Assign the existing CSS palette to named series without mutating agent data.
15
+ * @param input Series in display order, with stable keys independent of display labels.
16
+ * @param options Optional legacy color override, applied to every series.
17
+ * @returns A config keyed by series identity, including duplicate display labels.
18
+ * @complexity O(n) time and space for n series; no I/O.
19
+ */
20
+ export declare function createChartConfig({ series }: {
21
+ readonly series: readonly SeriesInput[];
22
+ }, { color }?: {
23
+ readonly color?: string | undefined;
24
+ }): ChartConfig;
25
+ /**
26
+ * Format chart numbers with Intl; preserve categorical strings without numeric coercion.
27
+ * @param input The value supplied by an axis, tooltip, legend or donut total.
28
+ * @param options Compact notation for ticks/totals, standard notation for exact values.
29
+ * @returns Display text, or an empty string for a missing value.
30
+ * @complexity O(k) time and space for k characters in the formatted value; no I/O.
31
+ */
32
+ export declare function formatChartValue({ value }: {
33
+ readonly value: unknown;
34
+ }, { notation }?: {
35
+ readonly notation?: 'standard' | 'compact';
36
+ }): string;
37
+ /** Recharts callback convention is positional; all formatting delegates to the shared owner. */
38
+ export declare const chartTickFormatter: (value: unknown) => string;
39
+ export {};
40
+ //# sourceMappingURL=chart-config.d.ts.map
@@ -0,0 +1,32 @@
1
+ import { CHART_SERIES_COLORS } from './chart-tokens.js';
2
+ /**
3
+ * Assign the existing CSS palette to named series without mutating agent data.
4
+ * @param input Series in display order, with stable keys independent of display labels.
5
+ * @param options Optional legacy color override, applied to every series.
6
+ * @returns A config keyed by series identity, including duplicate display labels.
7
+ * @complexity O(n) time and space for n series; no I/O.
8
+ */
9
+ export function createChartConfig({ series }, { color } = {}) {
10
+ return Object.fromEntries(series.map((entry, index) => [entry.key, {
11
+ label: entry.label,
12
+ color: color ?? CHART_SERIES_COLORS[index % CHART_SERIES_COLORS.length],
13
+ ...(entry.value === undefined ? {} : { value: entry.value }),
14
+ }]));
15
+ }
16
+ /**
17
+ * Format chart numbers with Intl; preserve categorical strings without numeric coercion.
18
+ * @param input The value supplied by an axis, tooltip, legend or donut total.
19
+ * @param options Compact notation for ticks/totals, standard notation for exact values.
20
+ * @returns Display text, or an empty string for a missing value.
21
+ * @complexity O(k) time and space for k characters in the formatted value; no I/O.
22
+ */
23
+ export function formatChartValue({ value }, { notation = 'standard' } = {}) {
24
+ if (value == null)
25
+ return '';
26
+ if (typeof value !== 'number')
27
+ return String(value);
28
+ return new Intl.NumberFormat('en-US', { notation, maximumFractionDigits: notation === 'compact' ? 1 : 20 }).format(value);
29
+ }
30
+ /** Recharts callback convention is positional; all formatting delegates to the shared owner. */
31
+ export const chartTickFormatter = (value) => formatChartValue({ value }, { notation: 'compact' });
32
+ //# sourceMappingURL=chart-config.js.map
@@ -15,7 +15,7 @@
15
15
  * "Claude orange should be the default color" (owner, 2026-10-05). The values live in CSS, never
16
16
  * here, so a host's theme stays the single owner of color.
17
17
  */
18
- /** Categorical series colors in fixed order (assign by position, never cycle past the end silently). */
18
+ /** Categorical series colors in fixed order; larger datasets repeat the palette with named legends. */
19
19
  export declare const CHART_SERIES_COLORS: readonly ["var(--jini-chart-1, var(--jini-chart-default-1))", "var(--jini-chart-2, var(--jini-chart-default-2))", "var(--jini-chart-3, var(--jini-chart-default-3))", "var(--jini-chart-4, var(--jini-chart-default-4))", "var(--jini-chart-5, var(--jini-chart-default-5))", "var(--jini-chart-6, var(--jini-chart-default-6))"];
20
20
  /** The single-series color (bar fill, line stroke). */
21
21
  export declare const CHART_PRIMARY_COLOR: "var(--jini-chart-1, var(--jini-chart-default-1))";
@@ -24,20 +24,26 @@ export declare const CHART_GRID_STROKE = "var(--jini-chart-grid, var(--jini-bord
24
24
  /** Axis tick label props: muted ink, never the series color. */
25
25
  export declare const CHART_AXIS_TICK: {
26
26
  readonly fill: "var(--jini-chart-axis, var(--jini-muted))";
27
+ readonly fontSize: 12;
28
+ };
29
+ /** Shared axis chrome; category visibility and numeric formatting remain separate concerns. */
30
+ export declare const CHART_AXIS_PROPS: {
31
+ readonly tick: {
32
+ readonly fill: "var(--jini-chart-axis, var(--jini-muted))";
33
+ readonly fontSize: 12;
34
+ };
35
+ readonly tickLine: false;
36
+ readonly axisLine: false;
37
+ readonly tickMargin: 10;
38
+ };
39
+ /** Hover points use the same series ink, with a surface halo in either color scheme. */
40
+ export declare const CHART_ACTIVE_DOT: {
41
+ readonly r: 5;
42
+ readonly stroke: "var(--jini-chart-surface, var(--jini-bg))";
43
+ readonly strokeWidth: 2;
27
44
  };
28
45
  /** The hover band behind a hovered bar (recharts' default is an opaque grey block). */
29
46
  export declare const CHART_CURSOR: {
30
47
  readonly fill: "var(--jini-chart-cursor, var(--jini-accent-soft))";
31
48
  };
32
- /** Tooltip box: theme surface and ink, so it does not stay a white box in dark mode. */
33
- export declare const CHART_TOOLTIP_CONTENT_STYLE: {
34
- readonly background: "var(--jini-chart-surface, var(--jini-bg))";
35
- readonly border: "1px solid var(--jini-chart-grid, var(--jini-border))";
36
- readonly borderRadius: "var(--jini-radius-sm)";
37
- readonly color: "var(--jini-chart-text, var(--jini-text))";
38
- };
39
- /** Tooltip label and value ink: text tokens, never the series color (recharts' item default). */
40
- export declare const CHART_TOOLTIP_TEXT_STYLE: {
41
- readonly color: "var(--jini-chart-text, var(--jini-text))";
42
- };
43
49
  //# sourceMappingURL=chart-tokens.d.ts.map
@@ -15,7 +15,7 @@
15
15
  * "Claude orange should be the default color" (owner, 2026-10-05). The values live in CSS, never
16
16
  * here, so a host's theme stays the single owner of color.
17
17
  */
18
- /** Categorical series colors in fixed order (assign by position, never cycle past the end silently). */
18
+ /** Categorical series colors in fixed order; larger datasets repeat the palette with named legends. */
19
19
  export const CHART_SERIES_COLORS = [
20
20
  'var(--jini-chart-1, var(--jini-chart-default-1))',
21
21
  'var(--jini-chart-2, var(--jini-chart-default-2))',
@@ -29,16 +29,11 @@ export const CHART_PRIMARY_COLOR = CHART_SERIES_COLORS[0];
29
29
  /** Grid lines and axis lines: recessive. */
30
30
  export const CHART_GRID_STROKE = 'var(--jini-chart-grid, var(--jini-border))';
31
31
  /** Axis tick label props: muted ink, never the series color. */
32
- export const CHART_AXIS_TICK = { fill: 'var(--jini-chart-axis, var(--jini-muted))' };
32
+ export const CHART_AXIS_TICK = { fill: 'var(--jini-chart-axis, var(--jini-muted))', fontSize: 12 };
33
+ /** Shared axis chrome; category visibility and numeric formatting remain separate concerns. */
34
+ export const CHART_AXIS_PROPS = { tick: CHART_AXIS_TICK, tickLine: false, axisLine: false, tickMargin: 10 };
35
+ /** Hover points use the same series ink, with a surface halo in either color scheme. */
36
+ export const CHART_ACTIVE_DOT = { r: 5, stroke: 'var(--jini-chart-surface, var(--jini-bg))', strokeWidth: 2 };
33
37
  /** The hover band behind a hovered bar (recharts' default is an opaque grey block). */
34
38
  export const CHART_CURSOR = { fill: 'var(--jini-chart-cursor, var(--jini-accent-soft))' };
35
- /** Tooltip box: theme surface and ink, so it does not stay a white box in dark mode. */
36
- export const CHART_TOOLTIP_CONTENT_STYLE = {
37
- background: 'var(--jini-chart-surface, var(--jini-bg))',
38
- border: `1px solid ${CHART_GRID_STROKE}`,
39
- borderRadius: 'var(--jini-radius-sm)',
40
- color: 'var(--jini-chart-text, var(--jini-text))',
41
- };
42
- /** Tooltip label and value ink: text tokens, never the series color (recharts' item default). */
43
- export const CHART_TOOLTIP_TEXT_STYLE = { color: 'var(--jini-chart-text, var(--jini-text))' };
44
39
  //# sourceMappingURL=chart-tokens.js.map
@@ -0,0 +1,31 @@
1
+ import { type ReactElement, type ReactNode } from 'react';
2
+ import { type ChartConfig } from './chart-config.js';
3
+ interface ChartContainerProps {
4
+ readonly config: ChartConfig;
5
+ readonly title: string;
6
+ readonly description: string;
7
+ readonly children: ReactElement;
8
+ }
9
+ /** Shared, measurable chart frame with an accessible caption and a wrapping legend. */
10
+ export declare function ChartContainer({ config, title, description, children }: ChartContainerProps): ReactElement;
11
+ interface ChartTooltipEntry {
12
+ readonly dataKey?: unknown;
13
+ readonly name?: string | number;
14
+ readonly value?: unknown;
15
+ readonly color?: string;
16
+ readonly type?: string;
17
+ readonly payload?: {
18
+ readonly _jiniChartKey?: string;
19
+ };
20
+ }
21
+ interface ChartTooltipContentProps {
22
+ readonly active?: boolean;
23
+ readonly label?: ReactNode;
24
+ readonly payload?: readonly ChartTooltipEntry[];
25
+ }
26
+ /** Shadcn-style tooltip card; series config owns both labels and swatch colors. */
27
+ export declare function ChartTooltipContent({ active, label, payload }: ChartTooltipContentProps): ReactElement | null;
28
+ /** Compact named legend; pie values remain readable without hover or outside labels. */
29
+ export declare function ChartLegendContent(): ReactElement | null;
30
+ export {};
31
+ //# sourceMappingURL=chart.d.ts.map
@@ -0,0 +1,34 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { createContext, useContext, useId } from 'react';
3
+ import { ResponsiveContainer } from 'recharts';
4
+ import { formatChartValue } from './chart-config.js';
5
+ import { CHART_PRIMARY_COLOR } from './chart-tokens.js';
6
+ const ChartContext = createContext({});
7
+ /** Shared, measurable chart frame with an accessible caption and a wrapping legend. */
8
+ export function ChartContainer({ config, title, description, children }) {
9
+ const id = useId();
10
+ return (_jsx(ChartContext.Provider, { value: config, children: _jsxs("figure", { className: "jini-chart", "aria-label": title, "aria-describedby": `${id}-description`, children: [_jsxs("figcaption", { className: "jini-chart-caption", children: [_jsx("span", { children: title }), _jsx("span", { id: `${id}-description`, children: description })] }), _jsx(ResponsiveContainer, { width: "100%", height: 300, minWidth: 0, children: children }), _jsx(ChartLegendContent, {})] }) }));
11
+ }
12
+ /** Shadcn-style tooltip card; series config owns both labels and swatch colors. */
13
+ export function ChartTooltipContent({ active, label, payload = [] }) {
14
+ const config = useContext(ChartContext);
15
+ const entries = payload.filter((entry) => entry.type !== 'none' && entry.value != null);
16
+ if (!active || entries.length === 0)
17
+ return null;
18
+ return (_jsxs("div", { className: "jini-chart-tooltip", role: "tooltip", "aria-live": "polite", "aria-atomic": "true", children: [label != null && _jsx("div", { className: "jini-chart-tooltip-label", children: label }), _jsx("div", { className: "jini-chart-tooltip-items", children: entries.map((entry, index) => {
19
+ // Pie names may repeat; its internal key keeps swatches tied to the actual slice.
20
+ const dataKey = String(entry.dataKey ?? entry.name);
21
+ const key = Object.hasOwn(config, dataKey) ? dataKey : entry.payload?._jiniChartKey ?? dataKey;
22
+ const series = Object.hasOwn(config, key) ? config[key] : undefined;
23
+ return (_jsxs("div", { className: "jini-chart-tooltip-item", children: [_jsx("span", { className: "jini-chart-swatch", style: { backgroundColor: series?.color ?? entry.color ?? CHART_PRIMARY_COLOR }, "aria-hidden": "true" }), _jsx("span", { className: "jini-chart-tooltip-name", children: series?.label ?? String(entry.name ?? entry.dataKey ?? 'Value') }), _jsx("span", { className: "jini-chart-tooltip-value", children: formatChartValue({ value: entry.value }) })] }, `${key}-${index}`));
24
+ }) })] }));
25
+ }
26
+ /** Compact named legend; pie values remain readable without hover or outside labels. */
27
+ export function ChartLegendContent() {
28
+ const config = useContext(ChartContext);
29
+ const entries = Object.entries(config);
30
+ if (entries.length === 0)
31
+ return null;
32
+ return (_jsx("ul", { className: "jini-chart-legend", "aria-label": "Chart legend", children: entries.map(([key, series]) => (_jsxs("li", { className: "jini-chart-legend-item", children: [_jsx("span", { className: "jini-chart-swatch", style: { backgroundColor: series.color }, "aria-hidden": "true" }), _jsx("span", { children: series.label }), series.value !== undefined && _jsx("span", { className: "jini-chart-legend-value", children: formatChartValue({ value: series.value }) })] }, key))) }));
33
+ }
34
+ //# sourceMappingURL=chart.js.map
@@ -1,7 +1,14 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { CartesianGrid, Line, LineChart as RechartsLineChart, ResponsiveContainer, Tooltip, XAxis, YAxis } from 'recharts';
3
- import { CHART_AXIS_TICK, CHART_GRID_STROKE, CHART_PRIMARY_COLOR, CHART_TOOLTIP_CONTENT_STYLE, CHART_TOOLTIP_TEXT_STYLE } from './chart-tokens.js';
2
+ import { useId } from 'react';
3
+ import { Area, CartesianGrid, ComposedChart, Line, Tooltip, XAxis, YAxis } from 'recharts';
4
+ import { CHART_ACTIVE_DOT, CHART_AXIS_PROPS, CHART_GRID_STROKE, CHART_PRIMARY_COLOR } from './chart-tokens.js';
5
+ import { chartTickFormatter, createChartConfig } from './chart-config.js';
6
+ import { ChartContainer, ChartTooltipContent } from './chart.js';
4
7
  export function LineChart({ data, categoryKey, valueKey, color = CHART_PRIMARY_COLOR }) {
5
- return (_jsx(ResponsiveContainer, { width: "100%", height: 300, children: _jsxs(RechartsLineChart, { data: data, children: [_jsx(CartesianGrid, { strokeDasharray: "3 3", stroke: CHART_GRID_STROKE, vertical: false }), _jsx(XAxis, { dataKey: categoryKey, interval: 0, tick: CHART_AXIS_TICK, stroke: CHART_GRID_STROKE, tickLine: false }), _jsx(YAxis, { tick: CHART_AXIS_TICK, stroke: CHART_GRID_STROKE, tickLine: false, axisLine: false }), _jsx(Tooltip, { cursor: { stroke: CHART_GRID_STROKE }, contentStyle: CHART_TOOLTIP_CONTENT_STYLE, labelStyle: CHART_TOOLTIP_TEXT_STYLE, itemStyle: CHART_TOOLTIP_TEXT_STYLE }), _jsx(Line, { type: "monotone", dataKey: valueKey, stroke: color, strokeWidth: 2, isAnimationActive: false })] }) }));
8
+ const gradientId = `jini-chart-area-${useId().replace(/:/g, '')}`;
9
+ const config = createChartConfig({ series: [{ key: valueKey, label: valueKey }] }, { color });
10
+ const title = `${valueKey} by ${categoryKey}`;
11
+ const description = `Line chart with ${data.length} points. Use arrow keys to explore values.`;
12
+ return (_jsx(ChartContainer, { config: config, title: title, description: description, children: _jsxs(ComposedChart, { data: data, accessibilityLayer: true, title: title, desc: description, margin: { top: 16, right: 12, bottom: 8, left: 0 }, children: [_jsx("defs", { children: _jsxs("linearGradient", { id: gradientId, x1: "0", y1: "0", x2: "0", y2: "1", children: [_jsx("stop", { offset: "0%", stopColor: config[valueKey].color, stopOpacity: 0.22 }), _jsx("stop", { offset: "100%", stopColor: config[valueKey].color, stopOpacity: 0.02 })] }) }), _jsx(CartesianGrid, { strokeDasharray: "3 3", stroke: CHART_GRID_STROKE, strokeOpacity: 0.6, vertical: false }), _jsx(XAxis, { dataKey: categoryKey, interval: 0, ...CHART_AXIS_PROPS }), _jsx(YAxis, { ...CHART_AXIS_PROPS, tickFormatter: chartTickFormatter, width: 48 }), _jsx(Tooltip, { cursor: { stroke: CHART_GRID_STROKE, strokeDasharray: '3 3' }, content: _jsx(ChartTooltipContent, {}), payloadUniqBy: (entry) => entry.graphicalItemId, isAnimationActive: false }), _jsx(Area, { type: "monotone", dataKey: valueKey, stroke: "none", fill: `url(#${gradientId})`, tooltipType: "none", legendType: "none", activeDot: false, isAnimationActive: false }), _jsx(Line, { type: "monotone", dataKey: valueKey, stroke: config[valueKey].color, strokeWidth: 2.5, dot: false, activeDot: CHART_ACTIVE_DOT, isAnimationActive: false })] }) }));
6
13
  }
7
14
  //# sourceMappingURL=line-chart.js.map
@@ -1,7 +1,12 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Cell, Pie, PieChart as RechartsPieChart, ResponsiveContainer, Tooltip } from 'recharts';
3
- import { CHART_PRIMARY_COLOR, CHART_SERIES_COLORS, CHART_TOOLTIP_CONTENT_STYLE, CHART_TOOLTIP_TEXT_STYLE } from './chart-tokens.js';
2
+ import { Cell, Pie, PieChart as RechartsPieChart, Tooltip } from 'recharts';
3
+ import { createChartConfig, formatChartValue } from './chart-config.js';
4
+ import { ChartContainer, ChartTooltipContent } from './chart.js';
4
5
  export function PieChart({ data, color }) {
5
- return (_jsx(ResponsiveContainer, { width: "100%", height: 300, children: _jsxs(RechartsPieChart, { children: [_jsx(Tooltip, { contentStyle: CHART_TOOLTIP_CONTENT_STYLE, labelStyle: CHART_TOOLTIP_TEXT_STYLE, itemStyle: CHART_TOOLTIP_TEXT_STYLE }), _jsx(Pie, { data: data, dataKey: "value", nameKey: "name", cx: "50%", cy: "50%", outerRadius: 100, label: true, isAnimationActive: false, children: data.map((entry, index) => (_jsx(Cell, { fill: color ?? CHART_SERIES_COLORS[index % CHART_SERIES_COLORS.length] ?? CHART_PRIMARY_COLOR }, entry.name))) })] }) }));
6
+ const slices = data.map((entry, index) => ({ ...entry, _jiniChartKey: `slice-${index}` }));
7
+ const config = createChartConfig({ series: slices.map((entry) => ({ key: entry._jiniChartKey, label: entry.name, value: entry.value })) }, { color });
8
+ const total = data.reduce((sum, entry) => sum + entry.value, 0);
9
+ const description = `Donut chart with ${data.length} categories. Total: ${formatChartValue({ value: total })}. Values are listed in the legend.`;
10
+ return (_jsx(ChartContainer, { config: config, title: "Distribution", description: description, children: _jsxs(RechartsPieChart, { accessibilityLayer: true, title: "Distribution", desc: description, margin: { top: 12, right: 12, bottom: 12, left: 12 }, children: [_jsx(Tooltip, { content: _jsx(ChartTooltipContent, {}), isAnimationActive: false }), _jsx(Pie, { data: slices, dataKey: "value", nameKey: "name", cx: "50%", cy: "50%", innerRadius: "55%", outerRadius: "78%", paddingAngle: 3, cornerRadius: 5, stroke: "none", label: false, labelLine: false, isAnimationActive: false, children: slices.map((entry) => (_jsx(Cell, { fill: config[entry._jiniChartKey].color }, entry._jiniChartKey))) }), _jsxs("text", { x: "50%", y: "50%", textAnchor: "middle", dominantBaseline: "middle", className: "jini-chart-total", "aria-hidden": "true", children: [_jsx("tspan", { x: "50%", dy: "-0.2em", children: formatChartValue({ value: total }, { notation: 'compact' }) }), _jsx("tspan", { x: "50%", dy: "1.8em", className: "jini-chart-total-label", children: "Total" })] })] }) }));
6
11
  }
7
12
  //# sourceMappingURL=pie-chart.js.map
@@ -5,9 +5,13 @@ export interface DataTableColumn {
5
5
  export interface DataTableProps {
6
6
  readonly columns: readonly DataTableColumn[];
7
7
  readonly rows: readonly Record<string, unknown>[];
8
+ /** Local header sorting; defaults to true. Initial row order is always preserved. */
9
+ readonly sortable?: boolean;
10
+ /** Opt-in local paging; omitted means all rows, preserving existing callers. */
11
+ readonly pageSize?: number;
8
12
  /** Host-wired, not part of the agent-facing wire schema — see data-table.manifest.ts. */
9
13
  readonly onRowClick?: (row: Record<string, unknown>, index: number) => void;
10
14
  }
11
15
  /** Composes shadcn's real `table.tsx` primitives into the same `columns`/`rows`/`onRowClick` contract `native.data-table` exposes. */
12
- export declare function DataTable({ columns, rows, onRowClick }: DataTableProps): import("react").JSX.Element;
16
+ export declare function DataTable({ columns, rows, onRowClick, sortable, pageSize }: DataTableProps): import("react").JSX.Element;
13
17
  //# sourceMappingURL=data-table.d.ts.map
@@ -1,7 +1,31 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useMemo, useState } from 'react';
3
+ import { getNumericColumnKeys, sortTableRows } from '../../table-data.js';
2
4
  import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from './table.js';
3
5
  /** Composes shadcn's real `table.tsx` primitives into the same `columns`/`rows`/`onRowClick` contract `native.data-table` exposes. */
4
- export function DataTable({ columns, rows, onRowClick }) {
5
- return (_jsxs(Table, { children: [_jsx(TableHeader, { children: _jsx(TableRow, { children: columns.map((column) => (_jsx(TableHead, { children: column.label }, column.key))) }) }), _jsx(TableBody, { children: rows.map((row, index) => (_jsx(TableRow, { onClick: onRowClick ? () => onRowClick(row, index) : undefined, role: onRowClick ? 'button' : undefined, children: columns.map((column) => (_jsx(TableCell, { children: String(row[column.key] ?? '') }, column.key))) }, index))) })] }));
6
+ export function DataTable({ columns, rows, onRowClick, sortable = true, pageSize }) {
7
+ const [sort, setSort] = useState(null);
8
+ const [requestedPage, setPage] = useState(0);
9
+ const numericKeys = useMemo(() => getNumericColumnKeys({ columns, rows }), [columns, rows]);
10
+ const activeSort = sortable && columns.some((column) => column.key === sort?.key) ? sort : null;
11
+ const sortedRows = useMemo(() => sortTableRows({ rows, sort: activeSort, numericKeys }), [rows, activeSort, numericKeys]);
12
+ const requestedSize = pageSize !== undefined && Number.isInteger(pageSize) && pageSize > 0 ? pageSize : null;
13
+ const paging = requestedSize !== null;
14
+ const size = requestedSize ?? Math.max(rows.length, 1);
15
+ const pageCount = Math.max(1, Math.ceil(rows.length / size));
16
+ // Clamp during render so a smaller result set never shows a stale, empty page.
17
+ const page = paging ? Math.min(requestedPage, pageCount - 1) : 0;
18
+ const start = page * size;
19
+ const visibleRows = sortedRows.slice(start, start + size);
20
+ return (_jsxs("div", { className: "jini-data-table-frame", "data-table-provider": "shadcn", children: [_jsxs(Table, { className: "jini-data-table", children: [_jsx(TableHeader, { children: _jsx(TableRow, { children: columns.map((column) => (_jsx(TableHead, { scope: "col", "data-numeric": numericKeys.has(column.key), "aria-sort": sortable ? (activeSort?.key === column.key ? activeSort.direction : 'none') : undefined, children: sortable ? (_jsxs("button", { type: "button", className: "jini-data-table-sort", onClick: () => {
21
+ setSort({ key: column.key, direction: activeSort?.key === column.key && activeSort.direction === 'ascending'
22
+ ? 'descending' : 'ascending' });
23
+ setPage(0);
24
+ }, children: [_jsx("span", { children: column.label }), _jsx("span", { "aria-hidden": "true", children: activeSort?.key === column.key ? (activeSort.direction === 'ascending' ? '↑' : '↓') : '↕' })] })) : column.label }, column.key))) }) }), _jsxs(TableBody, { children: [rows.length === 0 && _jsx(TableRow, { children: _jsx(TableCell, { className: "jini-data-table-empty", colSpan: columns.length, children: "No results." }) }), visibleRows.map(({ row, index }) => (_jsx(TableRow, { onClick: onRowClick ? () => onRowClick(row, index) : undefined, role: onRowClick ? 'button' : undefined, tabIndex: onRowClick ? 0 : undefined, onKeyDown: onRowClick ? (event) => {
25
+ if (event.target === event.currentTarget && (event.key === 'Enter' || event.key === ' ')) {
26
+ event.preventDefault();
27
+ onRowClick(row, index);
28
+ }
29
+ } : undefined, children: columns.map((column) => (_jsx(TableCell, { "data-numeric": numericKeys.has(column.key), children: String(row[column.key] ?? '') }, column.key))) }, index)))] })] }), paging && (_jsxs("div", { className: "jini-data-table-pagination", children: [_jsxs("span", { "aria-live": "polite", children: [rows.length === 0 ? 0 : start + 1, "\u2013", Math.min(start + size, rows.length), " of ", rows.length, " rows"] }), _jsxs("div", { className: "jini-data-table-pagination-controls", children: [_jsx("button", { type: "button", "aria-label": "Previous page", disabled: page === 0, onClick: () => setPage(page - 1), children: "Previous" }), _jsx("button", { type: "button", "aria-label": "Next page", disabled: page >= pageCount - 1, onClick: () => setPage(page + 1), children: "Next" })] })] }))] }));
6
30
  }
7
31
  //# sourceMappingURL=data-table.js.map
@@ -1,7 +1,8 @@
1
1
  import { z } from 'zod';
2
2
  import type { InteractiveComponentManifest } from '../../types.js';
3
3
  /**
4
- * Same wire shape as `native.data-table` (see that manifest) — same capabilities, so
4
+ * Same required wire shape as `native.data-table` (see that manifest), plus optional local
5
+ * sorting/paging settings — shared capabilities, so
5
6
  * `resolveByCapability('data-table')` returns both, proving the fallback-chain mechanic across
6
7
  * two real providers. `.passthrough()` for the same reason as that manifest: an A2UI-embedded
7
8
  * instance may carry an `action` prop this schema doesn't itself validate.
@@ -18,6 +19,8 @@ export declare const shadcnDataTablePropsSchema: z.ZodObject<{
18
19
  label: string;
19
20
  }>, "many">;
20
21
  rows: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">;
22
+ sortable: z.ZodOptional<z.ZodBoolean>;
23
+ pageSize: z.ZodOptional<z.ZodNumber>;
21
24
  }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
22
25
  columns: z.ZodArray<z.ZodObject<{
23
26
  key: z.ZodString;
@@ -30,6 +33,8 @@ export declare const shadcnDataTablePropsSchema: z.ZodObject<{
30
33
  label: string;
31
34
  }>, "many">;
32
35
  rows: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">;
36
+ sortable: z.ZodOptional<z.ZodBoolean>;
37
+ pageSize: z.ZodOptional<z.ZodNumber>;
33
38
  }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
34
39
  columns: z.ZodArray<z.ZodObject<{
35
40
  key: z.ZodString;
@@ -42,6 +47,8 @@ export declare const shadcnDataTablePropsSchema: z.ZodObject<{
42
47
  label: string;
43
48
  }>, "many">;
44
49
  rows: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">;
50
+ sortable: z.ZodOptional<z.ZodBoolean>;
51
+ pageSize: z.ZodOptional<z.ZodNumber>;
45
52
  }, z.ZodTypeAny, "passthrough">>;
46
53
  export declare const shadcnDataTableManifest: InteractiveComponentManifest;
47
54
  //# sourceMappingURL=data-table.manifest.d.ts.map