@iris-ui-kit/vue 0.2.29 → 0.2.30

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 (53) hide show
  1. package/dist/admin.cjs +29 -3
  2. package/dist/admin.cjs.map +1 -1
  3. package/dist/admin.js +3 -3
  4. package/dist/{chunk-X7Y35UUL.js → chunk-3547J6IN.js} +3 -3
  5. package/dist/{chunk-X7Y35UUL.js.map → chunk-3547J6IN.js.map} +1 -1
  6. package/dist/{chunk-BVKOOTXG.js → chunk-IAG64CHL.js} +3 -3
  7. package/dist/chunk-IAG64CHL.js.map +1 -0
  8. package/dist/{chunk-KSJZLFAT.js → chunk-MO7AAXA6.js} +6 -6
  9. package/dist/chunk-MO7AAXA6.js.map +1 -0
  10. package/dist/{chunk-EZUDM4TM.js → chunk-PT6X4543.js} +31 -5
  11. package/dist/chunk-PT6X4543.js.map +1 -0
  12. package/dist/{chunk-W3JMJVEK.js → chunk-TCAXRWT6.js} +3 -3
  13. package/dist/chunk-TCAXRWT6.js.map +1 -0
  14. package/dist/{chunk-KAOPZNZF.js → chunk-UPC4GN3F.js} +3 -3
  15. package/dist/chunk-UPC4GN3F.js.map +1 -0
  16. package/dist/{chunk-X5UOY4IV.js → chunk-W64OMUBD.js} +3 -3
  17. package/dist/{chunk-X5UOY4IV.js.map → chunk-W64OMUBD.js.map} +1 -1
  18. package/dist/{chunk-OH4YSGFK.js → chunk-ZTPIXL7Q.js} +3 -3
  19. package/dist/chunk-ZTPIXL7Q.js.map +1 -0
  20. package/dist/error-boundary.cjs +1 -1
  21. package/dist/error-boundary.cjs.map +1 -1
  22. package/dist/error-boundary.js +2 -2
  23. package/dist/form.cjs +1 -1
  24. package/dist/form.cjs.map +1 -1
  25. package/dist/form.js +1 -1
  26. package/dist/i18n.cjs +1 -1
  27. package/dist/i18n.cjs.map +1 -1
  28. package/dist/i18n.js +1 -1
  29. package/dist/index.cjs +437 -42
  30. package/dist/index.cjs.map +1 -1
  31. package/dist/index.d.cts +28 -3
  32. package/dist/index.d.ts +28 -3
  33. package/dist/index.js +416 -47
  34. package/dist/index.js.map +1 -1
  35. package/dist/provider.cjs +4 -4
  36. package/dist/provider.cjs.map +1 -1
  37. package/dist/provider.js +4 -4
  38. package/dist/skeletons.cjs +1 -1
  39. package/dist/skeletons.cjs.map +1 -1
  40. package/dist/skeletons.js +2 -2
  41. package/dist/skins.cjs +1 -1
  42. package/dist/skins.cjs.map +1 -1
  43. package/dist/skins.js +1 -1
  44. package/dist/theme.cjs +1 -1
  45. package/dist/theme.cjs.map +1 -1
  46. package/dist/theme.js +1 -1
  47. package/package.json +15 -15
  48. package/dist/chunk-BVKOOTXG.js.map +0 -1
  49. package/dist/chunk-EZUDM4TM.js.map +0 -1
  50. package/dist/chunk-KAOPZNZF.js.map +0 -1
  51. package/dist/chunk-KSJZLFAT.js.map +0 -1
  52. package/dist/chunk-OH4YSGFK.js.map +0 -1
  53. package/dist/chunk-W3JMJVEK.js.map +0 -1
package/dist/index.js CHANGED
@@ -6,13 +6,13 @@ export { IrisGrid } from './chunk-IN3DQ55U.js';
6
6
  import './chunk-4FQ7XF52.js';
7
7
  import { useDataState } from './chunk-S43IHHBU.js';
8
8
  export { DATA_STATE_CLASS, __resetDataStateStyles, installDataStateStyles, useDataState, usePrefersReducedMotion } from './chunk-S43IHHBU.js';
9
- export { IrisProvider, PluginStoreContextKey, usePlugin, usePluginStore } from './chunk-KSJZLFAT.js';
9
+ export { IrisProvider, PluginStoreContextKey, usePlugin, usePluginStore } from './chunk-MO7AAXA6.js';
10
10
  export { createClientFetcher, createResourceController, useResourceController } from './chunk-25NYWSXP.js';
11
- import { IrisCheckbox, IrisFormField, IrisInput, IrisButton } from './chunk-X5UOY4IV.js';
12
- export { IrisAlert, IrisButton, IrisCheckbox, IrisDashboardTemplate, IrisDivider, IrisFormField, IrisInput, IrisLoginTemplate, IrisPasswordInput } from './chunk-X5UOY4IV.js';
11
+ import { IrisCheckbox, IrisFormField, IrisInput, IrisButton } from './chunk-W64OMUBD.js';
12
+ export { IrisAlert, IrisButton, IrisCheckbox, IrisDashboardTemplate, IrisDivider, IrisFormField, IrisInput, IrisLoginTemplate, IrisPasswordInput } from './chunk-W64OMUBD.js';
13
13
  export { IrisContainer, IrisDashboardCard, IrisDashboardGrid, IrisStack } from './chunk-3R3QDLJC.js';
14
- export { IrisSkinKey, SkinProvider, SkinResolutionError, applySkin, builtinSkins, createSkinCatalog, createSkinEngine, createSkinRegistry, darkSkin, lightSkin, loadSkin, localStorageSkinStorage, memorySkinStorage, renderSkinStyle, resolveSkin, skinBootScript, skinError, skinToCssEntries, useSkin, useSkinContext, validateSkin } from './chunk-KAOPZNZF.js';
15
- export { DropdownContextKey, IrisAdminBreadcrumb, IrisAdminLayout, IrisAdminTabs, IrisBreadcrumb, IrisBreadcrumbItem, IrisDropdown, IrisDropdownItem, IrisDropdownMenu, IrisDropdownSeparator, IrisDropdownTrigger, IrisIcon, IrisNavMenu, createAdminPreferences, createTabsNav, filterNavByAccess, findNavNode, findNavPath, firstLeaf, flattenNav, isBranch, isClosable, localStorageAdminPreferencesStorage, nodeAllowsRoles, useAdminPreferences, useAdminShell, useTabsNav, visibleNav } from './chunk-EZUDM4TM.js';
14
+ export { IrisSkinKey, SkinProvider, SkinResolutionError, applySkin, builtinSkins, createSkinCatalog, createSkinEngine, createSkinRegistry, darkSkin, lightSkin, loadSkin, localStorageSkinStorage, memorySkinStorage, renderSkinStyle, resolveSkin, skinBootScript, skinError, skinToCssEntries, useSkin, useSkinContext, validateSkin } from './chunk-UPC4GN3F.js';
15
+ export { DropdownContextKey, IrisAdminBreadcrumb, IrisAdminLayout, IrisAdminTabs, IrisBreadcrumb, IrisBreadcrumbItem, IrisDropdown, IrisDropdownItem, IrisDropdownMenu, IrisDropdownSeparator, IrisDropdownTrigger, IrisIcon, IrisNavMenu, createAdminPreferences, createTabsNav, filterNavByAccess, findNavNode, findNavPath, firstLeaf, flattenNav, isBranch, isClosable, localStorageAdminPreferencesStorage, nodeAllowsRoles, useAdminPreferences, useAdminShell, useTabsNav, visibleNav } from './chunk-PT6X4543.js';
16
16
  import { useFloating, useDismiss } from './chunk-IPR5JAVF.js';
17
17
  export { useDismiss, useFloating } from './chunk-IPR5JAVF.js';
18
18
  import { useMachine } from './chunk-NNOF7KUH.js';
@@ -20,20 +20,20 @@ export { useMachine } from './chunk-NNOF7KUH.js';
20
20
  import { findFirstElement, mergeSlotProps, composeRefs } from './chunk-F77KIPOH.js';
21
21
  export { IrisSlot, composeRefs, findFirstElement, mergeSlotProps } from './chunk-F77KIPOH.js';
22
22
  export { IrisHeaderLayout, IrisSidebarLayout } from './chunk-3V46HGRC.js';
23
- export { IrisThemeKey, ThemeProvider, useColorScheme, useDirection, useTheme, useThemeContext } from './chunk-OH4YSGFK.js';
23
+ export { IrisThemeKey, ThemeProvider, useColorScheme, useDirection, useTheme, useThemeContext } from './chunk-ZTPIXL7Q.js';
24
24
  export { useAsyncResource, usePaginatedResource } from './chunk-SJB5DIIY.js';
25
25
  import { useDrag } from './chunk-IOMKC5OI.js';
26
26
  export { IrisClickOutside, IrisCompose, IrisHotkey, IrisLongPress, IrisMovable, IrisResizable, useDrag } from './chunk-IOMKC5OI.js';
27
27
  export { IrisSortable, SORTABLE_ITEM_ATTR } from './chunk-W3B6E5GN.js';
28
28
  export { createClientDataSource, createDataSource, createGroupedView, useDataSource, useGroupedView } from './chunk-QBFYIDY7.js';
29
- export { IrisErrorBoundary } from './chunk-X7Y35UUL.js';
30
- export { FormInjectionKey, IrisForm, useField, useFieldArray, useForm, useFormContext } from './chunk-BVKOOTXG.js';
29
+ export { IrisErrorBoundary } from './chunk-3547J6IN.js';
30
+ export { FormInjectionKey, IrisForm, useField, useFieldArray, useForm, useFormContext } from './chunk-IAG64CHL.js';
31
31
  import { useStore } from './chunk-75GSYEJS.js';
32
32
  export { useStore, useStoreSelector } from './chunk-75GSYEJS.js';
33
- import { useI18n } from './chunk-W3JMJVEK.js';
34
- export { I18nInjectionKey, IrisI18nProvider, useI18n } from './chunk-W3JMJVEK.js';
33
+ import { useI18n } from './chunk-TCAXRWT6.js';
34
+ export { I18nInjectionKey, IrisI18nProvider, useI18n } from './chunk-TCAXRWT6.js';
35
35
  import { defineComponent, computed, watch, ref, useId, provide, inject, h, nextTick, Teleport, onScopeDispose, Fragment, onMounted, watchEffect, onBeforeUnmount, onBeforeMount, shallowRef, toValue, Comment, onUnmounted } from 'vue';
36
- import { createFloatingMachine, createHoverIntent, createVirtualizer, createKeyboardNav, getPageRange, createSelectionModel, flattenLeafColumns, buildHeaderMatrix, detectColumnType, seedFormValues, createExpansion, flattenTree, withSortedChildren, mergeFormFilters, createTreeSelection, createCellRange, createSortable, compareStates, createStore, firstEnabledIndex, createCalendarNav, clampDate, startOfMonth, isSameMonth, buildMonthMatrix, getWeekdayNames, formatMonthYear, startOfDay, endOfMonth, isSameDay, isOutOfRange, formatLocalISO, hexToRgba, rgbaToHsva, hsvaToRgba, rgbToHex, addMonths, RESPONSIVE_NARROW_WIDTH, computeResponsiveColumns, createRemoteTableSource, readTableViews, computeVirtualRange, toCsvRows, removeRowsFromList, tableDisplayText, aggregate, previewColumnsFromRows, nextEnabledIndex, copyText, clamp01, rowsFromCsv, compareValues, TABLE_VIEWS_SAVE_ITEM, uniqueTableTabs, leftPinnedCount, pinnedCountFromBudget, toCsv, createAutoDismiss, validateEditRulesAsync, writeClipboardText, serializeTableRange, nextGridCell, createReconnectingSource, createResilientFetcher, createDisposableScope, downloadFile, toSpreadsheetXml, generateId, buildFormValues, applyTableMask, writeTableViews } from '@iris-ui-kit/core';
36
+ import { createFloatingMachine, createHoverIntent, createVirtualizer, createKeyboardNav, getPageRange, createSelectionModel, formatClock, flattenLeafColumns, buildHeaderMatrix, detectColumnType, seedFormValues, createExpansion, createAuditLog, flattenTree, withSortedChildren, mergeFormFilters, createTreeSelection, createCellRange, createSortable, compareStates, createStore, firstEnabledIndex, createCalendarNav, clampDate, startOfMonth, isSameMonth, buildMonthMatrix, getWeekdayNames, formatMonthYear, startOfDay, endOfMonth, isSameDay, isOutOfRange, formatLocalISO, hexToRgba, rgbaToHsva, hsvaToRgba, rgbToHex, addMonths, RESPONSIVE_NARROW_WIDTH, computeResponsiveColumns, createRemoteTableSource, memoizedFormulaValue, readTableViews, computeVirtualRange, toCsvRows, removeRowsFromList, tableDisplayText, aggregate, previewColumnsFromRows, nextEnabledIndex, copyText, clamp01, rowsFromCsv, compareValues, TABLE_VIEWS_SAVE_ITEM, uniqueTableTabs, leftPinnedCount, pinnedCountFromBudget, toCsv, createAutoDismiss, validateEditRulesAsync, writeClipboardText, serializeTableRange, nextGridCell, createReconnectingSource, createResilientFetcher, createDisposableScope, downloadFile, toSpreadsheetXml, generateId, buildFormValues, applyTableMask, writeTableViews } from '@iris-ui-kit/core';
37
37
  export { addDays, addMonths, buildMonthMatrix, clamp01, clampDate, composeEventHandlers, createFloatingMachine, createMachine, createStore, endOfMonth, formatLocalISO, formatMonthYear, generateId, getPageRange, getWeekdayNames, hexToRgba, hsvToRgb, hsvaToRgba, isOutOfRange, isSameDay, isSameMonth, mergeProps, parseCsv, rgbToHex, rgbToHsv, rgbaToHsva, startOfDay, startOfMonth } from '@iris-ui-kit/core';
38
38
  import { getDirection } from '@iris-ui-kit/theme';
39
39
  export { applyTheme, createThemeStore, getCssVar, toCssVarName } from '@iris-ui-kit/theme';
@@ -77,7 +77,7 @@ function useDisposableScope() {
77
77
  }
78
78
 
79
79
  // src/primitives/popover/context.ts
80
- var PopoverContextKey = Symbol("IrisPopover");
80
+ var PopoverContextKey = /* @__PURE__ */ Symbol("IrisPopover");
81
81
 
82
82
  // src/primitives/popover/Popover.ts
83
83
  var IrisPopover = defineComponent({
@@ -408,12 +408,12 @@ var IrisTooltip = defineComponent({
408
408
  const triggerListeners = {
409
409
  onPointerenter: handleEnter,
410
410
  onPointerleave: handleLeave,
411
- onFocus: () => {
411
+ onFocus: (() => {
412
412
  if (!props.disabled) hi.open();
413
- },
414
- onBlur: () => {
413
+ }),
414
+ onBlur: (() => {
415
415
  if (!props.disabled) hi.close();
416
- }
416
+ })
417
417
  };
418
418
  const captureTriggerRef = (el) => {
419
419
  triggerRef.value = el ?? null;
@@ -482,7 +482,7 @@ var IrisTooltip = defineComponent({
482
482
  });
483
483
 
484
484
  // src/primitives/dialog/context.ts
485
- var DialogContextKey = Symbol("IrisDialog");
485
+ var DialogContextKey = /* @__PURE__ */ Symbol("IrisDialog");
486
486
 
487
487
  // src/primitives/dialog/Dialog.ts
488
488
  var IrisDialog = defineComponent({
@@ -779,7 +779,7 @@ var IrisDialogClose = defineComponent({
779
779
  });
780
780
 
781
781
  // src/primitives/drawer/context.ts
782
- var DrawerContextKey = Symbol("IrisDrawer");
782
+ var DrawerContextKey = /* @__PURE__ */ Symbol("IrisDrawer");
783
783
 
784
784
  // src/primitives/drawer/Drawer.ts
785
785
  var IrisDrawer = defineComponent({
@@ -2336,7 +2336,7 @@ var IrisSwitch = defineComponent({
2336
2336
  );
2337
2337
  }
2338
2338
  });
2339
- var RadioGroupKey = Symbol("IrisRadioGroup");
2339
+ var RadioGroupKey = /* @__PURE__ */ Symbol("IrisRadioGroup");
2340
2340
  var IrisRadioGroup = defineComponent({
2341
2341
  name: "IrisRadioGroup",
2342
2342
  props: {
@@ -3539,8 +3539,8 @@ var IrisSkeleton = defineComponent({
3539
3539
  onMounted(installSkeletonStyles);
3540
3540
  const style = computed(() => {
3541
3541
  const w = props.width !== void 0 ? toCss(props.width) : defaultWidth(props.shape);
3542
- const h101 = props.height !== void 0 ? toCss(props.height) : defaultHeight(props.shape, props.width);
3543
- return { width: w, height: h101 };
3542
+ const h102 = props.height !== void 0 ? toCss(props.height) : defaultHeight(props.shape, props.width);
3543
+ return { width: w, height: h102 };
3544
3544
  });
3545
3545
  return () => h("div", {
3546
3546
  ...attrs,
@@ -4460,7 +4460,7 @@ var IrisChip = defineComponent({
4460
4460
  });
4461
4461
 
4462
4462
  // src/primitives/accordion/context.ts
4463
- var AccordionContextKey = Symbol("IrisAccordion");
4463
+ var AccordionContextKey = /* @__PURE__ */ Symbol("IrisAccordion");
4464
4464
 
4465
4465
  // src/primitives/accordion/Accordion.ts
4466
4466
  var IrisAccordion = defineComponent({
@@ -4698,7 +4698,7 @@ var IrisAccordionItem = defineComponent({
4698
4698
  });
4699
4699
 
4700
4700
  // src/primitives/stepper/context.ts
4701
- var StepperContextKey = Symbol("IrisStepper");
4701
+ var StepperContextKey = /* @__PURE__ */ Symbol("IrisStepper");
4702
4702
 
4703
4703
  // src/primitives/stepper/Stepper.ts
4704
4704
  var IrisStepper = defineComponent({
@@ -4946,7 +4946,7 @@ var IrisStepperStep = defineComponent({
4946
4946
  });
4947
4947
 
4948
4948
  // src/primitives/toggle-group/context.ts
4949
- var ToggleGroupContextKey = Symbol("IrisToggleGroup");
4949
+ var ToggleGroupContextKey = /* @__PURE__ */ Symbol("IrisToggleGroup");
4950
4950
  var SIZE_PADDING = {
4951
4951
  sm: "4px 10px",
4952
4952
  md: "6px 14px",
@@ -5998,6 +5998,24 @@ var tableProps = {
5998
5998
  type: Object,
5999
5999
  default: void 0
6000
6000
  },
6001
+ /** Audit log (batch EN, iris 独有 — mirror react batch AT): when true,
6002
+ * every mutation commit appends ONE entry to a bounded (200) ring —
6003
+ * inline/row cell edits (recorded directly at the commit point, type
6004
+ * 'edit' + rowKey + column + old→new) and the row-list funnels available
6005
+ * here (removeRows — list diff, type 'remove'; loadData — list diff, type
6006
+ * 'edit', react commitRowList default parity). External re-feeds (parent
6007
+ * data / proxy refetch / rowDrag reorder) re-baseline the diff snapshot
6008
+ * and never record. The toolbar gains an audit trigger
6009
+ * (`data-iris-audit-trigger`) opening a floating panel
6010
+ * (`data-iris-audit-panel`, like the filter/context panels — Esc /
6011
+ * outside / scroll close) listing newest-first entries (seq +
6012
+ * `formatClock` time + type + rowKey + column + muted old→new);
6013
+ * `getAuditLog()` / `clearAuditLog()` on the exposed handle access the
6014
+ * trail programmatically (the seq never resets on clear — audit
6015
+ * integrity). Requires a toolbar render (the gate admits `auditLog` like
6016
+ * `densityToggle`). Additive — default off; off = zero push.
6017
+ */
6018
+ auditLog: { type: Boolean, default: false },
6001
6019
  columnVisibility: {
6002
6020
  type: Object,
6003
6021
  default: void 0
@@ -6048,10 +6066,28 @@ var DRAG_COL_WIDTH = 40;
6048
6066
  var DEFAULT_COL_WIDTH = 140;
6049
6067
  var DEFAULT_MIN_WIDTH = 60;
6050
6068
  var RESIZE_STEP = 16;
6069
+ function isEditableColumn(column) {
6070
+ return !!column.editable && !column.formula;
6071
+ }
6051
6072
  function getCellValue(row, column) {
6073
+ if (column.formula) return memoizedFormulaValue(column.formula, row);
6052
6074
  const key = column.dataIndex ?? column.key;
6053
6075
  return row[key];
6054
6076
  }
6077
+ function withComputedFormulaCells(rows, columns) {
6078
+ const formulaCols = columns.filter((c) => c.formula);
6079
+ if (formulaCols.length === 0) return rows;
6080
+ return rows.map((row) => {
6081
+ let shadow = null;
6082
+ for (const col of formulaCols) {
6083
+ const key = col.dataIndex ?? col.key;
6084
+ const next = shadow ?? { ...row };
6085
+ next[key] = memoizedFormulaValue(col.formula, row);
6086
+ shadow = next;
6087
+ }
6088
+ return shadow;
6089
+ });
6090
+ }
6055
6091
  function resolveSpan(occupied, rowIndex, columnIndex, method) {
6056
6092
  if (!method) return { rowspan: 1, colspan: 1 };
6057
6093
  const key = `${rowIndex}:${columnIndex}`;
@@ -6413,7 +6449,7 @@ var toolbarBtnStyle = {
6413
6449
  };
6414
6450
  function renderToolbarSection(ctx) {
6415
6451
  const tb = ctx.toolbar;
6416
- if (!tb && !ctx.densityToggle) return null;
6452
+ if (!tb && !ctx.densityToggle && !ctx.auditLog) return null;
6417
6453
  const toolChildren = [];
6418
6454
  if (tb?.title) {
6419
6455
  toolChildren.push(
@@ -6567,6 +6603,28 @@ function renderToolbarSection(ctx) {
6567
6603
  )
6568
6604
  );
6569
6605
  }
6606
+ if (ctx.auditLog) {
6607
+ toolChildren.push(
6608
+ h(
6609
+ "button",
6610
+ {
6611
+ ref: (el) => {
6612
+ ctx.auditAnchorRef.value = el ?? null;
6613
+ },
6614
+ type: "button",
6615
+ "data-iris-audit-trigger": "",
6616
+ "aria-label": ctx.t("table.audit"),
6617
+ title: ctx.t("table.audit"),
6618
+ onClick: ctx.onAuditToggle,
6619
+ style: {
6620
+ ...toolbarBtnStyle,
6621
+ color: ctx.auditOpen.value ? "var(--iris-foreground)" : "var(--iris-muted)"
6622
+ }
6623
+ },
6624
+ "\u2630"
6625
+ )
6626
+ );
6627
+ }
6570
6628
  return h(
6571
6629
  "div",
6572
6630
  {
@@ -6787,6 +6845,233 @@ function renderFilterPanelSection(ctx) {
6787
6845
  );
6788
6846
  return h(Teleport, { to: "body" }, [node]);
6789
6847
  }
6848
+ function auditDiff(prev, next, resolveKey) {
6849
+ const len = Math.max(prev.length, next.length);
6850
+ for (let i = 0; i < len; i += 1) {
6851
+ const a = prev[i];
6852
+ const b = next[i];
6853
+ if (a === b) continue;
6854
+ if (!a || !b) return { rowKey: a ? resolveKey(a, i) : resolveKey(b, i) };
6855
+ const ka = resolveKey(a, i);
6856
+ const kb = resolveKey(b, i);
6857
+ if (ka !== kb) {
6858
+ return { rowKey: prev.length > next.length ? ka : kb };
6859
+ }
6860
+ const fields = /* @__PURE__ */ new Set();
6861
+ Object.keys(a).forEach((f) => fields.add(f));
6862
+ Object.keys(b).forEach((f) => fields.add(f));
6863
+ for (const f of fields) {
6864
+ if (a[f] !== b[f]) {
6865
+ return { rowKey: ka, column: f, oldValue: a[f], newValue: b[f] };
6866
+ }
6867
+ }
6868
+ }
6869
+ return void 0;
6870
+ }
6871
+ function renderAuditPanelSection(ctx) {
6872
+ if (!ctx.open.value) return null;
6873
+ return h(Teleport, { to: "body" }, [
6874
+ h(TableAuditPanel, {
6875
+ audit: ctx.audit,
6876
+ styles: ctx.styles.value,
6877
+ panelRef: ctx.panelRef,
6878
+ onClear: ctx.onClear,
6879
+ t: ctx.t
6880
+ })
6881
+ ]);
6882
+ }
6883
+ var TableAuditPanel = defineComponent({
6884
+ name: "TableAuditPanel",
6885
+ props: {
6886
+ audit: { type: Object, required: true },
6887
+ styles: { type: Object, required: true },
6888
+ panelRef: { type: Object, required: true },
6889
+ onClear: { type: Function, required: true },
6890
+ t: { type: Function, required: true }
6891
+ },
6892
+ setup(props) {
6893
+ const entries = ref(props.audit.list());
6894
+ let unsubscribe = null;
6895
+ onMounted(() => {
6896
+ unsubscribe = props.audit.subscribe(() => {
6897
+ entries.value = props.audit.list();
6898
+ });
6899
+ });
6900
+ onScopeDispose(() => {
6901
+ unsubscribe?.();
6902
+ unsubscribe = null;
6903
+ });
6904
+ return () => {
6905
+ const items = entries.value;
6906
+ return h(
6907
+ "div",
6908
+ {
6909
+ ref: (el) => {
6910
+ props.panelRef.value = el ?? null;
6911
+ },
6912
+ role: "dialog",
6913
+ "aria-label": props.t("table.audit"),
6914
+ "data-iris-audit-panel": "",
6915
+ style: {
6916
+ ...props.styles,
6917
+ zIndex: "var(--iris-z-popover, 1000)",
6918
+ background: "var(--iris-surface-floating, var(--iris-surface))",
6919
+ color: "var(--iris-foreground)",
6920
+ border: "1px solid var(--iris-border)",
6921
+ borderRadius: "var(--iris-radius-md, 6px)",
6922
+ boxShadow: "var(--iris-shadow-lg)",
6923
+ padding: "var(--iris-space-sm, 12px)",
6924
+ minWidth: 280,
6925
+ maxWidth: 360,
6926
+ display: "flex",
6927
+ flexDirection: "column",
6928
+ gap: "var(--iris-space-xs, 8px)",
6929
+ fontSize: "var(--iris-font-size-sm, 13px)"
6930
+ }
6931
+ },
6932
+ [
6933
+ h(
6934
+ "div",
6935
+ { style: { display: "flex", alignItems: "center", gap: "var(--iris-space-xs, 8px)" } },
6936
+ [
6937
+ h("span", { style: { fontWeight: 600, flex: 1 } }, props.t("table.audit")),
6938
+ items.length > 0 ? h(
6939
+ "button",
6940
+ {
6941
+ type: "button",
6942
+ "data-iris-audit-clear": "",
6943
+ onClick: props.onClear,
6944
+ style: {
6945
+ border: "1px solid var(--iris-border)",
6946
+ borderRadius: "var(--iris-radius-sm, 4px)",
6947
+ background: "transparent",
6948
+ color: "var(--iris-muted)",
6949
+ cursor: "pointer",
6950
+ padding: "var(--iris-space-xxs, 4px) var(--iris-space-xs, 8px)",
6951
+ fontSize: "var(--iris-font-size-xs, 12px)"
6952
+ }
6953
+ },
6954
+ props.t("table.audit.clear")
6955
+ ) : null
6956
+ ]
6957
+ ),
6958
+ items.length === 0 ? h(
6959
+ "div",
6960
+ {
6961
+ "data-iris-audit-empty": "",
6962
+ style: {
6963
+ color: "var(--iris-muted)",
6964
+ textAlign: "center",
6965
+ padding: "var(--iris-space-sm, 12px)"
6966
+ }
6967
+ },
6968
+ props.t("table.audit.empty")
6969
+ ) : h(
6970
+ "div",
6971
+ {
6972
+ "data-iris-audit-entries": "",
6973
+ style: {
6974
+ display: "flex",
6975
+ flexDirection: "column",
6976
+ gap: "var(--iris-space-xxs, 4px)",
6977
+ maxHeight: 240,
6978
+ overflowY: "auto"
6979
+ }
6980
+ },
6981
+ items.map(
6982
+ (e) => h(
6983
+ "div",
6984
+ {
6985
+ key: e.seq,
6986
+ "data-iris-audit-entry": "",
6987
+ style: {
6988
+ display: "flex",
6989
+ alignItems: "baseline",
6990
+ gap: "var(--iris-space-xs, 8px)",
6991
+ padding: "var(--iris-space-xxs, 4px) 0",
6992
+ borderBottom: "1px solid var(--iris-border-subtle, var(--iris-border))",
6993
+ fontSize: "var(--iris-font-size-xs, 12px)"
6994
+ }
6995
+ },
6996
+ [
6997
+ h(
6998
+ "span",
6999
+ {
7000
+ "data-iris-audit-seq": "",
7001
+ style: { color: "var(--iris-muted)", minWidth: 30 }
7002
+ },
7003
+ `#${e.seq}`
7004
+ ),
7005
+ h(
7006
+ "span",
7007
+ {
7008
+ "data-iris-audit-time": "",
7009
+ style: { color: "var(--iris-muted)", minWidth: 64 }
7010
+ },
7011
+ formatClock(new Date(e.at))
7012
+ ),
7013
+ h(
7014
+ "span",
7015
+ {
7016
+ "data-iris-audit-type": "",
7017
+ style: {
7018
+ color: "var(--iris-primary)",
7019
+ fontWeight: 600,
7020
+ textTransform: "uppercase"
7021
+ }
7022
+ },
7023
+ e.type
7024
+ ),
7025
+ h(
7026
+ "span",
7027
+ {
7028
+ "data-iris-audit-rowkey": "",
7029
+ style: { color: "var(--iris-foreground)" }
7030
+ },
7031
+ e.rowKey !== void 0 ? String(e.rowKey) : "\u2014"
7032
+ ),
7033
+ e.column !== void 0 ? h(
7034
+ "span",
7035
+ {
7036
+ "data-iris-audit-cell": "",
7037
+ style: { color: "var(--iris-muted)", flex: 1 }
7038
+ },
7039
+ [
7040
+ e.column,
7041
+ h(
7042
+ "span",
7043
+ {
7044
+ style: {
7045
+ display: "inline-flex",
7046
+ gap: "var(--iris-space-xxs, 4px)",
7047
+ marginInlineStart: "var(--iris-space-xs, 8px)"
7048
+ }
7049
+ },
7050
+ [
7051
+ h(
7052
+ "span",
7053
+ { "data-iris-audit-old": "" },
7054
+ String(e.oldValue ?? "")
7055
+ ),
7056
+ h("span", { "aria-hidden": "true" }, "\u2192"),
7057
+ h(
7058
+ "span",
7059
+ { "data-iris-audit-new": "" },
7060
+ String(e.newValue ?? "")
7061
+ )
7062
+ ]
7063
+ )
7064
+ ]
7065
+ ) : null
7066
+ ]
7067
+ )
7068
+ )
7069
+ )
7070
+ ]
7071
+ );
7072
+ };
7073
+ }
7074
+ });
6790
7075
  function renderImportPreviewSection(ctx) {
6791
7076
  if (!ctx.rows) return null;
6792
7077
  const columns = previewColumnsFromRows(ctx.rows);
@@ -7114,9 +7399,10 @@ function createTableKeyboard(options) {
7114
7399
  const range = activeCellRange();
7115
7400
  const clip = options.clipConfig();
7116
7401
  if (!range || clip?.copy === false) return;
7402
+ const rows = withComputedFormulaCells(options.rows(), options.columns());
7117
7403
  void writeClipboardText(
7118
7404
  serializeTableRange(
7119
- options.rows(),
7405
+ rows,
7120
7406
  options.columns(),
7121
7407
  range,
7122
7408
  clip?.copyFormat,
@@ -8060,10 +8346,9 @@ var IrisTable = defineComponent({
8060
8346
  detectTypesDone.value = true;
8061
8347
  const next = {};
8062
8348
  for (const column of flattenLeafColumns(props.columns)) {
8063
- const candidate = column;
8064
- if (candidate.formula) continue;
8349
+ if (column.formula) continue;
8065
8350
  next[column.key] = detectColumnType(
8066
- tableData.value.map((row) => getCellValue(row, candidate))
8351
+ tableData.value.map((row) => getCellValue(row, column))
8067
8352
  );
8068
8353
  }
8069
8354
  detectedTypes.value = next;
@@ -8200,6 +8485,17 @@ var IrisTable = defineComponent({
8200
8485
  if (typeof v === "string" || typeof v === "number") return v;
8201
8486
  return index;
8202
8487
  };
8488
+ const audit = createAuditLog();
8489
+ const auditRowsRef = ref(tableData.value);
8490
+ watch(tableData, (next) => {
8491
+ auditRowsRef.value = next;
8492
+ });
8493
+ const recordAudit = (next, type) => {
8494
+ if (!props.auditLog) return;
8495
+ const entry = auditDiff(auditRowsRef.value, next, (r, i) => rowId(r, i));
8496
+ if (entry) audit.push({ type, ...entry });
8497
+ auditRowsRef.value = next;
8498
+ };
8203
8499
  const treeMode = computed(() => props.getSubRows !== void 0 || props.lazyLoad !== void 0);
8204
8500
  const lazyChildren = ref(/* @__PURE__ */ new Map());
8205
8501
  const lazyLoading = ref(/* @__PURE__ */ new Set());
@@ -8349,7 +8645,7 @@ var IrisTable = defineComponent({
8349
8645
  const editError = ref(null);
8350
8646
  const editorInputRef = ref(null);
8351
8647
  const beginEdit = (row, column, rowIdent) => {
8352
- if (!column.editable) return;
8648
+ if (!isEditableColumn(column)) return;
8353
8649
  editingCellId.value = cellId(rowIdent, column.key);
8354
8650
  editingColumnKey.value = column.key;
8355
8651
  const current = getCellValue(row, column);
@@ -8389,6 +8685,15 @@ var IrisTable = defineComponent({
8389
8685
  };
8390
8686
  const writeCellValue = (row, column, rowIndex, oldValue, newValue) => {
8391
8687
  if (newValue === oldValue) return;
8688
+ if (props.auditLog) {
8689
+ audit.push({
8690
+ type: "edit",
8691
+ rowKey: rowId(row, rowIndex),
8692
+ column: column.dataIndex ?? column.key,
8693
+ oldValue,
8694
+ newValue
8695
+ });
8696
+ }
8392
8697
  emit("cellEdit", { row, column, oldValue, newValue, rowIndex });
8393
8698
  if (proxyCtrl.proxy.value) {
8394
8699
  const id = rowId(row, rowIndex);
@@ -8422,7 +8727,7 @@ var IrisTable = defineComponent({
8422
8727
  const currentRowFor = (k) => bodyData.value.find((r, i) => rowId(r, i) === k);
8423
8728
  const beginRowEdit = (row, rowIndex, focusColKey) => {
8424
8729
  const k = rowId(row, rowIndex);
8425
- const editableCols = leafColumns.value.filter((c) => c.editable);
8730
+ const editableCols = leafColumns.value.filter(isEditableColumn);
8426
8731
  if (editableCols.length === 0) return;
8427
8732
  const sessions = /* @__PURE__ */ new Map();
8428
8733
  for (const col of editableCols) {
@@ -8493,7 +8798,7 @@ var IrisTable = defineComponent({
8493
8798
  const handleRowModeCellClick = (row, col, index, k) => {
8494
8799
  if (rowEditing.value?.k === k) {
8495
8800
  const id = cellId(k, col.key);
8496
- if (col.editable && !rowSessions.value.has(id)) {
8801
+ if (isEditableColumn(col) && !rowSessions.value.has(id)) {
8497
8802
  const current = getCellValue(row, col);
8498
8803
  rowSessions.value.set(id, {
8499
8804
  draft: current == null ? "" : String(current),
@@ -8909,6 +9214,7 @@ var IrisTable = defineComponent({
8909
9214
  const spanOccupy = /* @__PURE__ */ new Set();
8910
9215
  const tableExpose = {
8911
9216
  loadData: (rows) => {
9217
+ recordAudit(rows, "edit");
8912
9218
  if (proxyCtrl.proxy.value) proxyCtrl.liveData.value = rows;
8913
9219
  else localRowsOverride.value = rows;
8914
9220
  props.onDataChange?.(rows);
@@ -8927,6 +9233,7 @@ var IrisTable = defineComponent({
8927
9233
  removeRows: (keys) => {
8928
9234
  const { rows, removedKeys } = removeRowsFromList(tableData.value, props.rowKey, keys);
8929
9235
  if (removedKeys.size === 0) return;
9236
+ recordAudit(rows, "remove");
8930
9237
  if (proxyCtrl.proxy.value) proxyCtrl.liveData.value = rows;
8931
9238
  else localRowsOverride.value = rows;
8932
9239
  const selected = displaySelection.value;
@@ -8938,9 +9245,15 @@ var IrisTable = defineComponent({
8938
9245
  props.onDataChange?.(rows);
8939
9246
  },
8940
9247
  getFilteredData: () => [...bodyData.value],
8941
- exportCurrentViewCsv: () => exportCsv(bodyData.value, leafColumns.value),
9248
+ exportCurrentViewCsv: () => exportCsv(
9249
+ withComputedFormulaCells(bodyData.value, leafColumns.value),
9250
+ leafColumns.value
9251
+ ),
8942
9252
  exportMultiCsv: () => {
8943
- const current = exportCsv(bodyData.value, leafColumns.value);
9253
+ const current = exportCsv(
9254
+ withComputedFormulaCells(bodyData.value, leafColumns.value),
9255
+ leafColumns.value
9256
+ );
8944
9257
  const names = props.exportNames;
8945
9258
  if (!names || names.length === 0) return current;
8946
9259
  const segments = [`# current${current ? `
@@ -8955,7 +9268,14 @@ ${refCsv}` : ""}`);
8955
9268
  },
8956
9269
  compareStates,
8957
9270
  scrollToRow,
8958
- goToRow
9271
+ goToRow,
9272
+ // Batch EN (iris 独有): audit trail programmatic access — a snapshot
9273
+ // (newest-first entries) and a wipe, both against the ref-once
9274
+ // controller; the seq counter never resets on clear (audit integrity).
9275
+ getAuditLog: () => audit.list(),
9276
+ clearAuditLog: () => {
9277
+ audit.clear();
9278
+ }
8959
9279
  };
8960
9280
  expose(tableExpose);
8961
9281
  const buildFormSection = () => renderFormSection({
@@ -8966,6 +9286,48 @@ ${refCsv}` : ""}`);
8966
9286
  handleFormSubmit,
8967
9287
  handleFormReset
8968
9288
  });
9289
+ const auditOpen = ref(false);
9290
+ const auditAnchorRef = ref(null);
9291
+ const auditPanelRef = ref(null);
9292
+ const toggleAuditPanel = () => {
9293
+ auditOpen.value = !auditOpen.value;
9294
+ };
9295
+ const closeAuditPanel = () => {
9296
+ auditOpen.value = false;
9297
+ };
9298
+ const clearAudit = () => {
9299
+ audit.clear();
9300
+ };
9301
+ const { floatingStyles: auditPanelStyles } = useFloating({
9302
+ anchor: auditAnchorRef,
9303
+ floating: auditPanelRef,
9304
+ open: auditOpen,
9305
+ placement: "bottom-end",
9306
+ flip: false,
9307
+ shift: true
9308
+ });
9309
+ useDismiss({
9310
+ enabled: auditOpen,
9311
+ exclude: [auditPanelRef, auditAnchorRef],
9312
+ onDismiss: closeAuditPanel
9313
+ });
9314
+ watch(auditOpen, (open) => {
9315
+ if (typeof document === "undefined") return;
9316
+ if (open) document.addEventListener("scroll", closeAuditPanel, true);
9317
+ else document.removeEventListener("scroll", closeAuditPanel, true);
9318
+ });
9319
+ onScopeDispose(() => {
9320
+ if (typeof document === "undefined") return;
9321
+ document.removeEventListener("scroll", closeAuditPanel, true);
9322
+ });
9323
+ const buildAuditPanelSection = () => renderAuditPanelSection({
9324
+ open: auditOpen,
9325
+ audit,
9326
+ styles: auditPanelStyles,
9327
+ panelRef: auditPanelRef,
9328
+ onClear: clearAudit,
9329
+ t
9330
+ });
8969
9331
  const buildToolbarSection = () => renderToolbarSection({
8970
9332
  toolbar: props.toolbar,
8971
9333
  selectable: props.selectable,
@@ -8976,7 +9338,13 @@ ${refCsv}` : ""}`);
8976
9338
  onImportFile: importController.handleImportFile,
8977
9339
  densityToggle: props.densityToggle,
8978
9340
  effectiveDensity: effectiveDensity.value,
8979
- onDensityToggle: cycleDensity
9341
+ onDensityToggle: cycleDensity,
9342
+ // Batch EN: the built-in audit trigger rides the toolbar (react
9343
+ // parity — the toolbar gate admits auditLog on its own).
9344
+ auditLog: props.auditLog,
9345
+ auditOpen,
9346
+ auditAnchorRef,
9347
+ onAuditToggle: toggleAuditPanel
8980
9348
  });
8981
9349
  const buildPagerSection = () => renderPagerSection({ proxyCtrl, proxyConfig: props.proxyConfig });
8982
9350
  const contextMenuState = ref(null);
@@ -9545,7 +9913,7 @@ ${refCsv}` : ""}`);
9545
9913
  rowSessions.value.get(editCellId)
9546
9914
  ) : buildCellEditContent(row, col, index, editCellId);
9547
9915
  } else {
9548
- content = cellSlot?.({ row, index, value: getCellValue(row, col) }) ?? tableDisplayText(row, col);
9916
+ content = cellSlot?.({ row, index, value: getCellValue(row, col) }) ?? tableDisplayText(row, col, getCellValue);
9549
9917
  }
9550
9918
  const treeIndent = treeMeta && ci === 0 ? buildTreeIndent(treeMeta, row) : null;
9551
9919
  const cellChildren = treeIndent ? [treeIndent, ...Array.isArray(content) ? content : [content]] : content;
@@ -9557,7 +9925,7 @@ ${refCsv}` : ""}`);
9557
9925
  role: "cell",
9558
9926
  "data-iris-table-cell": col.key,
9559
9927
  "data-iris-table-pinned": col.pinned,
9560
- "data-editable": col.editable ? "" : void 0,
9928
+ "data-editable": isEditableColumn(col) ? "" : void 0,
9561
9929
  "data-editing": isEditing ? "" : void 0,
9562
9930
  "data-iris-input-hint": patternHint ? "true" : void 0,
9563
9931
  // Grid keyboard navigation (opt-in): grid coords + roving tabindex
@@ -9583,11 +9951,11 @@ ${refCsv}` : ""}`);
9583
9951
  }
9584
9952
  }
9585
9953
  } : {},
9586
- onDblclick: rowMode.value ? () => switchRowEdit(row, index, col.key) : col.editable ? () => beginEdit(row, col, id) : void 0,
9954
+ onDblclick: rowMode.value ? () => switchRowEdit(row, index, col.key) : isEditableColumn(col) ? () => beginEdit(row, col, id) : void 0,
9587
9955
  onClick: rowMode.value ? () => handleRowModeCellClick(row, col, index, id) : props.cellRange ? (e) => {
9588
9956
  if (e.shiftKey) cellRangeCtrl.extendRange(index, ci);
9589
9957
  else cellRangeCtrl.startRange(index, ci);
9590
- } : col.editable && props.editConfig?.trigger === "click" ? () => beginEdit(row, col, id) : void 0,
9958
+ } : isEditableColumn(col) && props.editConfig?.trigger === "click" ? () => beginEdit(row, col, id) : void 0,
9591
9959
  onContextmenu: props.contextMenu ? (e) => handleContextMenu(e, row, col, index, ci) : void 0,
9592
9960
  style: {
9593
9961
  display: "flex",
@@ -9601,7 +9969,7 @@ ${refCsv}` : ""}`);
9601
9969
  whiteSpace: "nowrap",
9602
9970
  overflow: "hidden",
9603
9971
  textOverflow: "ellipsis",
9604
- cursor: col.editable ? "cell" : "default",
9972
+ cursor: isEditableColumn(col) ? "cell" : "default",
9605
9973
  ...props.cellRange && isInRange(index, ci) ? { background: "var(--iris-surface-selected, rgba(99,102,241,0.12))" } : {},
9606
9974
  ...visibleColSet.value ? { gridColumnStart: String(colTrack(ci)) } : {},
9607
9975
  ...colspan > 1 ? { gridColumnEnd: `span ${colspan}` } : {},
@@ -9823,7 +10191,8 @@ ${refCsv}` : ""}`);
9823
10191
  [h("span", { "aria-hidden": "true" }, "\u21C6"), h("span", t("table.scrollHint"))]
9824
10192
  ) : null,
9825
10193
  buildContextMenuSection(),
9826
- buildFilterPanelSection()
10194
+ buildFilterPanelSection(),
10195
+ buildAuditPanelSection()
9827
10196
  ].filter((n) => n !== null);
9828
10197
  return rootNodes.length === 1 ? rootNodes[0] : rootNodes;
9829
10198
  };
@@ -9849,7 +10218,7 @@ async function downloadExcel(filename, xml) {
9849
10218
  }
9850
10219
 
9851
10220
  // src/primitives/tabs/context.ts
9852
- var TabsContextKey = Symbol("IrisTabs");
10221
+ var TabsContextKey = /* @__PURE__ */ Symbol("IrisTabs");
9853
10222
 
9854
10223
  // src/primitives/tabs/Tabs.ts
9855
10224
  var IrisTabs = defineComponent({
@@ -10149,7 +10518,7 @@ var IrisTabsContent = defineComponent({
10149
10518
  });
10150
10519
 
10151
10520
  // src/primitives/menu/context.ts
10152
- var MenuContextKey = Symbol("IrisMenu");
10521
+ var MenuContextKey = /* @__PURE__ */ Symbol("IrisMenu");
10153
10522
 
10154
10523
  // src/primitives/menu/Menu.ts
10155
10524
  var IrisMenu = defineComponent({
@@ -16621,12 +16990,12 @@ function defaultFilter(query, item) {
16621
16990
  if (!q) return 0;
16622
16991
  const haystacks = [item.label, ...item.keywords ?? []].map((s) => s.toLowerCase());
16623
16992
  let best = null;
16624
- for (const h101 of haystacks) {
16993
+ for (const h102 of haystacks) {
16625
16994
  let qi = 0;
16626
16995
  let lastIdx = -1;
16627
16996
  let score = 0;
16628
- for (let i = 0; i < h101.length && qi < q.length; i += 1) {
16629
- if (h101[i] === q[qi]) {
16997
+ for (let i = 0; i < h102.length && qi < q.length; i += 1) {
16998
+ if (h102[i] === q[qi]) {
16630
16999
  score += lastIdx === -1 ? i : i - lastIdx - 1;
16631
17000
  lastIdx = i;
16632
17001
  qi += 1;