@squadbase/vantage 0.2.0 → 0.2.2

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.
@@ -260,7 +260,13 @@ interface EChartProps {
260
260
  */
261
261
  height?: string | number;
262
262
  loading?: boolean;
263
- /** `echarts.init` にそのまま渡すテーマ(名前または登録済みテーマオブジェクト)。 */
263
+ /**
264
+ * `echarts.init` にそのまま渡すテーマ(名前または登録済みテーマオブジェクト)。
265
+ *
266
+ * 渡すとデザイントークン追従は**完全に無効**になり、明暗の切り替えにも追従しなく
267
+ * なる。系列色だけ変えたいなら `option.color` を使う ― option はテーマより優先
268
+ * されるので、軸・凡例・ツールチップのトークン追従は残る。
269
+ */
264
270
  theme?: string | object;
265
271
  onEvents?: Record<string, (params: unknown) => void>;
266
272
  ariaLabel?: string;
@@ -1,6 +1,6 @@
1
- import { SidebarProvider, Sidebar, SidebarContent, SidebarGroup, SidebarGroupLabel, SidebarMenu, SidebarFooter, SidebarRail, SidebarInset, SidebarTrigger, Separator, Button, Input, Table, TableHeader, TableRow, TableHead, TableBody, TableCell, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuCheckboxItem, useIsMobile, Popover, PopoverTrigger, PopoverContent, Calendar, ToggleGroup, ToggleGroupItem, Badge, SelectGroup, SelectLabel, Collapsible, CollapsibleTrigger, SidebarMenuButton, SidebarMenuBadge, CollapsibleContent, SidebarMenuSub, SidebarMenuSubItem, SidebarMenuSubButton, SidebarMenuItem, Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem, Skeleton, Checkbox } from '../chunk-DIABD3KZ.js';
1
+ import { SidebarProvider, Sidebar, SidebarContent, SidebarGroup, SidebarGroupLabel, SidebarMenu, SidebarFooter, SidebarRail, SidebarInset, SidebarTrigger, Separator, Button, Input, Table, TableHeader, TableRow, TableHead, TableBody, TableCell, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuCheckboxItem, useIsMobile, Popover, PopoverTrigger, PopoverContent, Calendar, ToggleGroup, ToggleGroupItem, Badge, SelectGroup, SelectLabel, Collapsible, CollapsibleTrigger, SidebarMenuButton, SidebarMenuBadge, CollapsibleContent, SidebarMenuSub, SidebarMenuSubItem, SidebarMenuSubButton, SidebarMenuItem, Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem, Skeleton, Checkbox } from '../chunk-JC6MT5UU.js';
2
2
  import { cn } from '../chunk-A2UUGASH.js';
3
- import { forwardRef, useRef, useState, useEffect, useCallback, Fragment, createContext, useMemo, useId, useContext } from 'react';
3
+ import { forwardRef, useRef, useState, useEffect, useMemo, useCallback, Fragment, createContext, useId, useContext } from 'react';
4
4
  import { cva } from 'class-variance-authority';
5
5
  import { jsx, jsxs, Fragment as Fragment$1 } from 'react/jsx-runtime';
6
6
  import { Check, Copy, Download, Search, ArrowUp, ArrowDown, ArrowUpDown, Columns3, CalendarIcon, ChevronDownIcon, Minus, ChevronRight, XIcon, LoaderIcon, CheckIcon, ChevronDown, X } from 'lucide-react';
@@ -183,7 +183,6 @@ function NavSelect({
183
183
  return /* @__PURE__ */ jsxs(
184
184
  Select,
185
185
  {
186
- items: Object.fromEntries(allItems.map((item) => [item.href, item.label])),
187
186
  value: currentValue,
188
187
  onValueChange: (href) => {
189
188
  if (href !== null) onNavigate(href);
@@ -474,6 +473,123 @@ function DashboardCardPreset({
474
473
  footer && /* @__PURE__ */ jsx(DashboardCardFooter, { className: footerClassName, children: footer })
475
474
  ] });
476
475
  }
476
+
477
+ // src/components/chart-theme.ts
478
+ var SERIES_TOKENS = ["--chart-1", "--chart-2", "--chart-3", "--chart-4", "--chart-5"];
479
+ var normalizeContext;
480
+ function toCanvasColor(value) {
481
+ const raw = value.trim();
482
+ if (!raw) return null;
483
+ if (normalizeContext === void 0) {
484
+ normalizeContext = document.createElement("canvas").getContext("2d");
485
+ }
486
+ const ctx = normalizeContext;
487
+ if (!ctx) return raw;
488
+ ctx.fillStyle = "#000000";
489
+ ctx.fillStyle = raw;
490
+ const onBlack = ctx.fillStyle;
491
+ ctx.fillStyle = "#ffffff";
492
+ ctx.fillStyle = raw;
493
+ return onBlack === ctx.fillStyle ? onBlack : null;
494
+ }
495
+ function readChartTokens(el) {
496
+ if (typeof document === "undefined") return null;
497
+ const target = document.documentElement;
498
+ if (!target) return null;
499
+ const styles = getComputedStyle(target);
500
+ const read = (name) => toCanvasColor(styles.getPropertyValue(name));
501
+ const series = [];
502
+ for (const token of SERIES_TOKENS) {
503
+ const color = read(token);
504
+ if (color) series.push(color);
505
+ }
506
+ return {
507
+ series,
508
+ foreground: read("--foreground"),
509
+ mutedForeground: read("--muted-foreground"),
510
+ border: read("--border"),
511
+ popover: read("--popover"),
512
+ popoverForeground: read("--popover-foreground")
513
+ };
514
+ }
515
+ function sameChartTokens(a, b) {
516
+ if (a === b) return true;
517
+ if (!a || !b) return false;
518
+ return a.series.length === b.series.length && a.series.every((color, i) => color === b.series[i]) && a.foreground === b.foreground && a.mutedForeground === b.mutedForeground && a.border === b.border && a.popover === b.popover && a.popoverForeground === b.popoverForeground;
519
+ }
520
+ function watchChartTokens(onChange) {
521
+ if (typeof document === "undefined") return () => {
522
+ };
523
+ let frame = 0;
524
+ const schedule = () => {
525
+ if (frame) return;
526
+ frame = requestAnimationFrame(() => {
527
+ frame = 0;
528
+ onChange();
529
+ });
530
+ };
531
+ const themeObserver = new MutationObserver(schedule);
532
+ const attributeFilter = ["class", "style", "data-theme"];
533
+ themeObserver.observe(document.documentElement, { attributes: true, attributeFilter });
534
+ if (document.body) themeObserver.observe(document.body, { attributes: true, attributeFilter });
535
+ const styleObserver = new MutationObserver(schedule);
536
+ if (document.head) {
537
+ styleObserver.observe(document.head, {
538
+ childList: true,
539
+ subtree: true,
540
+ characterData: true,
541
+ attributes: true,
542
+ attributeFilter: ["href", "media", "disabled"]
543
+ });
544
+ }
545
+ const onLoad = (event) => {
546
+ if (event.target instanceof HTMLLinkElement) schedule();
547
+ };
548
+ document.addEventListener("load", onLoad, true);
549
+ const media = window.matchMedia("(prefers-color-scheme: dark)");
550
+ media.addEventListener("change", schedule);
551
+ return () => {
552
+ if (frame) cancelAnimationFrame(frame);
553
+ themeObserver.disconnect();
554
+ styleObserver.disconnect();
555
+ document.removeEventListener("load", onLoad, true);
556
+ media.removeEventListener("change", schedule);
557
+ };
558
+ }
559
+ function axisTheme(tokens, splitLine) {
560
+ const line = tokens.border ?? void 0;
561
+ return {
562
+ axisLine: { show: true, lineStyle: { color: line } },
563
+ axisTick: { show: true, lineStyle: { color: line } },
564
+ axisLabel: { show: true, color: tokens.mutedForeground ?? void 0 },
565
+ splitLine: { show: splitLine, lineStyle: { color: line ? [line] : void 0 } },
566
+ splitArea: { show: false }
567
+ };
568
+ }
569
+ function buildChartTheme(tokens) {
570
+ const text = tokens.foreground ?? void 0;
571
+ const muted = tokens.mutedForeground ?? void 0;
572
+ const line = tokens.border ?? void 0;
573
+ return {
574
+ // Let the page background show through: charts sit on cards, not on a canvas.
575
+ backgroundColor: "transparent",
576
+ ...tokens.series.length > 0 ? { color: tokens.series } : {},
577
+ textStyle: { color: text },
578
+ title: { textStyle: { color: text }, subtextStyle: { color: muted } },
579
+ legend: { textStyle: { color: muted } },
580
+ categoryAxis: axisTheme(tokens, false),
581
+ valueAxis: axisTheme(tokens, true),
582
+ logAxis: axisTheme(tokens, true),
583
+ timeAxis: axisTheme(tokens, true),
584
+ tooltip: {
585
+ backgroundColor: tokens.popover ?? void 0,
586
+ borderColor: line,
587
+ borderWidth: 1,
588
+ textStyle: { color: tokens.popoverForeground ?? void 0 },
589
+ axisPointer: { lineStyle: { color: line }, crossStyle: { color: line } }
590
+ }
591
+ };
592
+ }
477
593
  var EChart = forwardRef(function EChart2({
478
594
  option,
479
595
  height,
@@ -488,10 +604,24 @@ var EChart = forwardRef(function EChart2({
488
604
  const containerRef = useRef(null);
489
605
  const [instance, setInstance] = useState(null);
490
606
  const [copied, setCopied] = useState(false);
607
+ const [tokens, setTokens] = useState(() => readChartTokens());
608
+ useEffect(() => {
609
+ if (theme !== void 0) return;
610
+ const sync = () => {
611
+ setTokens((prev) => {
612
+ const next = readChartTokens();
613
+ return sameChartTokens(prev, next) ? prev : next;
614
+ });
615
+ };
616
+ sync();
617
+ return watchChartTokens(sync);
618
+ }, [theme]);
619
+ const autoTheme = useMemo(() => tokens ? buildChartTheme(tokens) : void 0, [tokens]);
620
+ const resolvedTheme = theme ?? autoTheme;
491
621
  useEffect(() => {
492
622
  const container = containerRef.current;
493
623
  if (!container) return;
494
- const inst = echarts.init(container, theme, { renderer: "canvas" });
624
+ const inst = echarts.init(container, resolvedTheme, { renderer: "canvas" });
495
625
  setInstance(inst);
496
626
  const observer = new ResizeObserver(() => inst.resize());
497
627
  observer.observe(container);
@@ -499,7 +629,7 @@ var EChart = forwardRef(function EChart2({
499
629
  observer.disconnect();
500
630
  inst.dispose();
501
631
  };
502
- }, [theme]);
632
+ }, [resolvedTheme]);
503
633
  useEffect(() => {
504
634
  if (!instance) return;
505
635
  instance.setOption(option, { notMerge: true, lazyUpdate: true });
@@ -1181,7 +1311,6 @@ var DataTablePagination = forwardRef(
1181
1311
  /* @__PURE__ */ jsxs(
1182
1312
  Select,
1183
1313
  {
1184
- items: Object.fromEntries(pageSizeOptions.map((size) => [String(size), `${size}\u4EF6`])),
1185
1314
  value: String(currentPageSize),
1186
1315
  onValueChange: (value) => table.setPageSize(Number(value)),
1187
1316
  children: [
@@ -1326,22 +1455,10 @@ function FilterBarSelect({
1326
1455
  }) {
1327
1456
  const { value, onChange } = useFilterBar();
1328
1457
  const handleChange = (selected) => onChange({ ...value, [filterKey]: selected ?? void 0 });
1329
- const items = useMemo(
1330
- () => Object.fromEntries(options.map((option) => [option.value, option.label])),
1331
- [options]
1332
- );
1333
- return /* @__PURE__ */ jsxs(
1334
- Select,
1335
- {
1336
- items,
1337
- value: value[filterKey] ?? "",
1338
- onValueChange: handleChange,
1339
- children: [
1340
- /* @__PURE__ */ jsx(SelectTrigger, { size: "sm", "aria-label": label, "data-slot": "filter-bar-select", className, children: /* @__PURE__ */ jsx(SelectValue, { placeholder: placeholder ?? label }) }),
1341
- /* @__PURE__ */ jsx(SelectContent, { children: options.map((option) => /* @__PURE__ */ jsx(SelectItem, { value: option.value, disabled: option.disabled, children: option.label }, option.value)) })
1342
- ]
1343
- }
1344
- );
1458
+ return /* @__PURE__ */ jsxs(Select, { value: value[filterKey] ?? "", onValueChange: handleChange, children: [
1459
+ /* @__PURE__ */ jsx(SelectTrigger, { size: "sm", "aria-label": label, "data-slot": "filter-bar-select", className, children: /* @__PURE__ */ jsx(SelectValue, { placeholder: placeholder ?? label }) }),
1460
+ /* @__PURE__ */ jsx(SelectContent, { children: options.map((option) => /* @__PURE__ */ jsx(SelectItem, { value: option.value, disabled: option.disabled, children: option.label }, option.value)) })
1461
+ ] });
1345
1462
  }
1346
1463
  FilterBarSelect.displayName = "FilterBarSelect";
1347
1464
  function FilterBarMultiSelect({