@stella-source/stellasource-dsl 5.1.1 → 5.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/README.md +13 -0
  2. package/dist/cjs/index.js +72 -25
  3. package/dist/cjs/index.js.map +1 -1
  4. package/dist/cjs/types/components/Table/types.d.ts +0 -1
  5. package/dist/cjs/types/components/Table/useTableState.d.ts +2 -1
  6. package/dist/cjs/types/components/TextField/NumberInput/NumberInput.d.ts +1 -1
  7. package/dist/cjs/types/components/TextField/NumberInput/types.d.ts +1 -0
  8. package/dist/cjs/types/components/TextField/PasswordInput/PasswordInput.d.ts +1 -1
  9. package/dist/cjs/types/components/TextField/PasswordInput/types.d.ts +1 -0
  10. package/dist/cjs/types/components/TextField/TextFieldContainer.d.ts +1 -1
  11. package/dist/cjs/types/components/TextField/TextInput/TextInput.d.ts +1 -1
  12. package/dist/cjs/types/components/TextField/TextInput/types.d.ts +1 -0
  13. package/dist/cjs/types/components/TextField/styles.d.ts +8 -2
  14. package/dist/cjs/types/components/TextField/types.d.ts +1 -0
  15. package/dist/esm/index.esm.js +72 -25
  16. package/dist/esm/index.esm.js.map +1 -1
  17. package/dist/esm/types/components/Table/types.d.ts +0 -1
  18. package/dist/esm/types/components/Table/useTableState.d.ts +2 -1
  19. package/dist/esm/types/components/TextField/NumberInput/NumberInput.d.ts +1 -1
  20. package/dist/esm/types/components/TextField/NumberInput/types.d.ts +1 -0
  21. package/dist/esm/types/components/TextField/PasswordInput/PasswordInput.d.ts +1 -1
  22. package/dist/esm/types/components/TextField/PasswordInput/types.d.ts +1 -0
  23. package/dist/esm/types/components/TextField/TextFieldContainer.d.ts +1 -1
  24. package/dist/esm/types/components/TextField/TextInput/TextInput.d.ts +1 -1
  25. package/dist/esm/types/components/TextField/TextInput/types.d.ts +1 -0
  26. package/dist/esm/types/components/TextField/styles.d.ts +8 -2
  27. package/dist/esm/types/components/TextField/types.d.ts +1 -0
  28. package/dist/index.d.ts +6 -4
  29. package/package.json +2 -1
package/README.md CHANGED
@@ -48,6 +48,19 @@ To get started with the **Stella Source Design System**, visit our [documentatio
48
48
 
49
49
  ---
50
50
 
51
+ # NPM Commands
52
+
53
+ | Command | Description |
54
+ |---|---|
55
+ | `npm run start` | Start Storybook dev server on port 6006 |
56
+ | `npm run build` | Build Storybook for production |
57
+ | `npm run package` | Build the component library with Rollup |
58
+ | `npm test` | Run tests in watch mode (Vitest) |
59
+ | `npm run test:coverage` | Run tests with coverage report |
60
+ | `npm run ngrok` | Expose local Storybook via ngrok (port 6006) |
61
+
62
+ ---
63
+
51
64
  # Contributing to the DSL
52
65
 
53
66
  Contributing Guide: https://dev.azure.com/stellasource/Stella%20Source/_wiki/wikis/SecturaSoft.wiki/543/Contributing-To-The-DSL
package/dist/cjs/index.js CHANGED
@@ -18177,12 +18177,24 @@ const IconButton = a$n.forwardRef(({ iconName, onClick, disabled, variant = "pri
18177
18177
 
18178
18178
  const Wrapper = styled.div `
18179
18179
  display: flex;
18180
- flex-direction: column;
18180
+ flex-direction: ${({ $labelPosition }) => $labelPosition === "left" ? "row" : "column"};
18181
+ align-items: ${({ $labelPosition }) => $labelPosition === "left" ? "flex-start" : "stretch"};
18182
+ gap: ${({ $labelPosition }) => ($labelPosition === "left" ? "10px" : "0")};
18181
18183
  min-width: 60px;
18182
18184
  max-width: 400px;
18183
18185
  position: relative;
18184
18186
  width: 100%;
18185
18187
  `;
18188
+ const InputColumn = styled.div `
18189
+ display: flex;
18190
+ flex-direction: column;
18191
+ flex: 1;
18192
+ `;
18193
+ const LabelAligner = styled.div `
18194
+ height: 32px;
18195
+ display: flex;
18196
+ align-items: center;
18197
+ `;
18186
18198
  const TextFieldWrapper = styled.div.attrs({
18187
18199
  className: "DSL-stella-textfield",
18188
18200
  }) `
@@ -18194,7 +18206,7 @@ const TextFieldWrapper = styled.div.attrs({
18194
18206
  border: 1px solid ${Styles.color.grey.medium};
18195
18207
  border-radius: 6px;
18196
18208
  overflow: hidden;
18197
- margin-top: 3px;
18209
+ margin-top: ${({ $labelPosition }) => $labelPosition === "left" ? "0" : "3px"};
18198
18210
  background-color: ${({ $isDisabled }) => $isDisabled ? Styles.color.grey.pale : "white"};
18199
18211
  outline: ${({ $hasError }) => $hasError && `${Styles.color.states.error} auto 1px`};
18200
18212
  cursor: ${({ $isDisabled, $isLoading }) => {
@@ -18253,10 +18265,9 @@ const IconContainer = styled.div `
18253
18265
  margin-right: 5px;
18254
18266
  `;
18255
18267
 
18256
- const TextFieldContainer = ({ id, label, children, tooltipText, endIcon, className, rightCategory, leftCategory, helperText, dataTestId, helperTextAffectLayout = true, disabled = false, hideLabel = false, isLoading = false, hasError = false, isRequired = false, }) => {
18257
- return (a$n.createElement(Wrapper, { "data-testid": dataTestId, className: className },
18258
- a$n.createElement(Label, { tooltipText: tooltipText, required: isRequired, labelValue: label, hideLabel: hideLabel, id: `${id}-label`, htmlFor: `${id}-text-field` }),
18259
- a$n.createElement(TextFieldWrapper, { id: id, "$hasError": hasError, "$isDisabled": disabled, "$isLoading": isLoading, "data-testid": "text-input-wrapper" },
18268
+ const TextFieldContainer = ({ id, label, children, tooltipText, endIcon, className, rightCategory, leftCategory, helperText, dataTestId, helperTextAffectLayout = true, disabled = false, hideLabel = false, isLoading = false, hasError = false, isRequired = false, labelPosition = "top", }) => {
18269
+ const inputAndHelper = (a$n.createElement(a$n.Fragment, null,
18270
+ a$n.createElement(TextFieldWrapper, { id: id, "$hasError": hasError, "$isDisabled": disabled, "$isLoading": isLoading, "$labelPosition": labelPosition, "data-testid": "text-input-wrapper" },
18260
18271
  leftCategory && a$n.createElement(Category, null, leftCategory),
18261
18272
  children,
18262
18273
  isLoading && (a$n.createElement(IconContainer, null,
@@ -18265,9 +18276,13 @@ const TextFieldContainer = ({ id, label, children, tooltipText, endIcon, classNa
18265
18276
  a$n.createElement(StellaIcon, { dataTestId: "end-icon", iconName: endIcon }))),
18266
18277
  rightCategory && a$n.createElement(Category, null, rightCategory)),
18267
18278
  helperText && (a$n.createElement(HelperText, { id: `${id}-helper-text`, text: helperText, affectLayout: helperTextAffectLayout, type: hasError ? "error" : "info" }))));
18279
+ return (a$n.createElement(Wrapper, { "data-testid": dataTestId, className: className, "$labelPosition": labelPosition },
18280
+ labelPosition === "left" ? (a$n.createElement(LabelAligner, null,
18281
+ a$n.createElement(Label, { tooltipText: tooltipText, required: isRequired, labelValue: label, hideLabel: hideLabel, id: `${id}-label`, htmlFor: `${id}-text-field` }))) : (a$n.createElement(Label, { tooltipText: tooltipText, required: isRequired, labelValue: label, hideLabel: hideLabel, id: `${id}-label`, htmlFor: `${id}-text-field` })),
18282
+ labelPosition === "left" ? (a$n.createElement(InputColumn, null, inputAndHelper)) : (inputAndHelper)));
18268
18283
  };
18269
18284
 
18270
- const TextInput = ({ id, className, htmlProps, label, onChange, onBlur, onFocus, value, isRequired, maxLength, tooltipText, helperText, endIcon, placeholder = "", textAlign = "left", helperTextAffectLayout = true, hideLabel = false, disabled = false, hasError = false, isLoading = false, ariaDescribedBy, enableAutocomplete = false, }) => {
18285
+ const TextInput = ({ id, className, htmlProps, label, onChange, onBlur, onFocus, value, isRequired, maxLength, tooltipText, helperText, endIcon, placeholder = "", textAlign = "left", helperTextAffectLayout = true, hideLabel = false, disabled = false, hasError = false, isLoading = false, ariaDescribedBy, enableAutocomplete = false, labelPosition, }) => {
18271
18286
  const containerProps = {
18272
18287
  id,
18273
18288
  label,
@@ -18283,6 +18298,7 @@ const TextInput = ({ id, className, htmlProps, label, onChange, onBlur, onFocus,
18283
18298
  endIcon,
18284
18299
  disabled,
18285
18300
  isLoading,
18301
+ labelPosition,
18286
18302
  };
18287
18303
  const [inputValue, setInputValue] = a$n.useState("");
18288
18304
  const valueToUse = value ?? inputValue;
@@ -18299,7 +18315,7 @@ const CustomIconButton$2 = styled(IconButton) `
18299
18315
  margin-right: 2px;
18300
18316
  `;
18301
18317
 
18302
- const PasswordInput = ({ id, className, htmlProps, label, placeholder = "Enter Password", onChange, onBlur, onFocus, value, isRequired, maxLength, tooltipText, helperText, textAlign = "left", isHidden = true, helperTextAffectLayout = true, hideLabel = false, disabled = false, hasError = false, ariaDescribedBy, enableAutocomplete = false, }) => {
18318
+ const PasswordInput = ({ id, className, htmlProps, label, placeholder = "Enter Password", onChange, onBlur, onFocus, value, isRequired, maxLength, tooltipText, helperText, textAlign = "left", isHidden = true, helperTextAffectLayout = true, hideLabel = false, disabled = false, hasError = false, ariaDescribedBy, enableAutocomplete = false, labelPosition, }) => {
18303
18319
  const containerProps = {
18304
18320
  id,
18305
18321
  label,
@@ -18313,6 +18329,7 @@ const PasswordInput = ({ id, className, htmlProps, label, placeholder = "Enter P
18313
18329
  leftCategory: undefined,
18314
18330
  hideLabel,
18315
18331
  disabled,
18332
+ labelPosition,
18316
18333
  };
18317
18334
  const [inputValue, setInputValue] = a$n.useState("");
18318
18335
  const [show, setShow] = a$n.useState(!isHidden);
@@ -18351,7 +18368,7 @@ const formatDynamicNumbersWithCommas = (num, decimalPlaces, isDegrees) => {
18351
18368
  : "";
18352
18369
  };
18353
18370
 
18354
- const NumberInput = ({ id, className, htmlProps, leftCategory, rightCategory, label, onChange, onBlur, onFocus, value, isRequired, maxLength, tooltipText, helperText, endIcon, placeholder = "0", textAlign = "left", isTruncated = false, helperTextAffectLayout = true, hideLabel = false, disabled = false, isLoading = false, hasError = false, thousandSeparator = true, decimalPlaces = 0, allowNegativeNumbers = false, ariaDescribedBy, enableAutocomplete = false, isDegrees = false, }) => {
18371
+ const NumberInput = ({ id, className, htmlProps, leftCategory, rightCategory, label, onChange, onBlur, onFocus, value, isRequired, maxLength, tooltipText, helperText, endIcon, placeholder = "0", textAlign = "left", isTruncated = false, helperTextAffectLayout = true, hideLabel = false, disabled = false, isLoading = false, hasError = false, thousandSeparator = true, decimalPlaces = 0, allowNegativeNumbers = false, ariaDescribedBy, enableAutocomplete = false, isDegrees = false, labelPosition, }) => {
18355
18372
  const containerProps = {
18356
18373
  id,
18357
18374
  label,
@@ -18367,6 +18384,7 @@ const NumberInput = ({ id, className, htmlProps, leftCategory, rightCategory, la
18367
18384
  leftCategory,
18368
18385
  hideLabel,
18369
18386
  disabled,
18387
+ labelPosition,
18370
18388
  };
18371
18389
  const [inputValue, setInputValue] = a$n.useState("");
18372
18390
  const [placeholderText, setPlaceholderText] = a$n.useState(placeholder);
@@ -21843,14 +21861,15 @@ function usePersistTableState(tableId, state, sizingDebounceMs = 300) {
21843
21861
  a$n.useEffect(() => {
21844
21862
  latestSizing.current = state.columnSizing;
21845
21863
  }, [state.columnSizing]);
21846
- // Persist visibility and sorting immediately
21864
+ // Persist visibility, sorting, and filters immediately
21847
21865
  a$n.useEffect(() => {
21848
21866
  saveTableState(tableId, {
21849
21867
  columnVisibility: state.columnVisibility,
21850
21868
  columnSizing: latestSizing.current,
21851
21869
  sorting: state.sorting,
21870
+ columnFilters: state.columnFilters,
21852
21871
  });
21853
- }, [tableId, state.columnVisibility, state.sorting]);
21872
+ }, [tableId, state.columnVisibility, state.sorting, state.columnFilters]);
21854
21873
  // Persist sizing debounced
21855
21874
  a$n.useEffect(() => {
21856
21875
  if (debounceTimer.current)
@@ -21860,6 +21879,7 @@ function usePersistTableState(tableId, state, sizingDebounceMs = 300) {
21860
21879
  columnVisibility: state.columnVisibility,
21861
21880
  columnSizing: latestSizing.current,
21862
21881
  sorting: state.sorting,
21882
+ columnFilters: state.columnFilters,
21863
21883
  });
21864
21884
  }, sizingDebounceMs);
21865
21885
  return () => {
@@ -22523,7 +22543,9 @@ const TableHeaderCell = ({ header, serverSide, filters, sorting, scrollPosition,
22523
22543
  }, 300);
22524
22544
  const displayOptions = serverSide
22525
22545
  ? filterOptions
22526
- : normalizeOptions(Array.from(header.column.getFacetedUniqueValues().keys()));
22546
+ : header.column.getCanFilter()
22547
+ ? normalizeOptions(Array.from(header.column.getFacetedUniqueValues().keys()))
22548
+ : [];
22527
22549
  a$n.useEffect(() => {
22528
22550
  setFilterOptions(normalizeOptions(meta?.filterOptions || []));
22529
22551
  }, [meta]);
@@ -22659,7 +22681,6 @@ function Table({ columns, data, isLoading, serverSide = false, onPageChange, onS
22659
22681
  const [localColumns, setLocalColumns] = a$n.useState(columns);
22660
22682
  const [totalData, setTotalData] = a$n.useState(paginationDetails?.totalRows);
22661
22683
  const [sorting, setSorting] = a$n.useState(() => loadTableState(id).sorting ?? []);
22662
- const [filters, setFilters] = a$n.useState({});
22663
22684
  const [rowState, setRowState] = a$n.useState({});
22664
22685
  const [columnVisibility, setColumnVisibility] = a$n.useState(() => {
22665
22686
  const persisted = loadTableState(id);
@@ -22673,7 +22694,8 @@ function Table({ columns, data, isLoading, serverSide = false, onPageChange, onS
22673
22694
  ]));
22674
22695
  });
22675
22696
  const [columnFilters, setColumnFilters] = a$n.useState(() => {
22676
- const base = defaultFilters ?? [];
22697
+ const persisted = loadTableState(id);
22698
+ const base = persisted.columnFilters ?? defaultFilters ?? [];
22677
22699
  if (!staticFilters?.length)
22678
22700
  return base;
22679
22701
  const merged = [...base];
@@ -22692,6 +22714,11 @@ function Table({ columns, data, isLoading, serverSide = false, onPageChange, onS
22692
22714
  });
22693
22715
  return merged;
22694
22716
  });
22717
+ const filters = a$n.useMemo(() => {
22718
+ const map = {};
22719
+ columnFilters.forEach((f) => (map[f.id] = f.value));
22720
+ return map;
22721
+ }, [columnFilters]);
22695
22722
  const [columnPinning, setColumnPinning] = a$n.useState({ left: ["select"], right: ["options"] });
22696
22723
  const scrollRef = a$n.useRef(null);
22697
22724
  const visibilityButtonRef = a$n.useRef(null);
@@ -22728,7 +22755,13 @@ function Table({ columns, data, isLoading, serverSide = false, onPageChange, onS
22728
22755
  setLocalData(data);
22729
22756
  if (paginationDetails && paginationDetails.startingPage !== pageIndex)
22730
22757
  setPageIndex(paginationDetails?.startingPage);
22731
- }, [paginationDetails, data, columns]);
22758
+ }, [
22759
+ paginationDetails?.totalRows,
22760
+ paginationDetails?.startingPage,
22761
+ paginationDetails?.rowsPerPage,
22762
+ data,
22763
+ columns,
22764
+ ]);
22732
22765
  a$n.useEffect(() => {
22733
22766
  if (!showVisibilityMenu)
22734
22767
  return;
@@ -22808,7 +22841,7 @@ function Table({ columns, data, isLoading, serverSide = false, onPageChange, onS
22808
22841
  !table.getIsAllPageRowsSelected();
22809
22842
  return (a$n.createElement(IndeterminateCheckbox, { isIndeterminate: isIndeterminate, isChecked: table.getIsAllPageRowsSelected(), onChange: table.getToggleAllPageRowsSelectedHandler() }));
22810
22843
  },
22811
- cell: ({ row }) => (a$n.createElement(Checkbox, { checked: row.getIsSelected(), onChange: row.getToggleSelectedHandler() })),
22844
+ cell: ({ row }) => (a$n.createElement(Checkbox, { checked: row.getIsSelected(), onChange: row.getToggleSelectedHandler(), onClick: (e) => e.stopPropagation() })),
22812
22845
  size: 20,
22813
22846
  });
22814
22847
  }
@@ -22894,9 +22927,6 @@ function Table({ columns, data, isLoading, serverSide = false, onPageChange, onS
22894
22927
  });
22895
22928
  }
22896
22929
  setColumnFilters(next);
22897
- const map = {};
22898
- next.forEach((f) => (map[f.id] = f.value));
22899
- setFilters(map);
22900
22930
  onFilterChange?.(next);
22901
22931
  },
22902
22932
  filterFns: {
@@ -22907,7 +22937,7 @@ function Table({ columns, data, isLoading, serverSide = false, onPageChange, onS
22907
22937
  },
22908
22938
  },
22909
22939
  });
22910
- usePersistTableState(id, { columnVisibility, sorting });
22940
+ usePersistTableState(id, { columnVisibility, sorting, columnFilters });
22911
22941
  a$n.useEffect(() => {
22912
22942
  if (onRowSelect) {
22913
22943
  const selectedData = table
@@ -22916,6 +22946,12 @@ function Table({ columns, data, isLoading, serverSide = false, onPageChange, onS
22916
22946
  onRowSelect?.(selectedData);
22917
22947
  }
22918
22948
  }, [rowSelection]);
22949
+ const initialColumnFilters = a$n.useRef(columnFilters);
22950
+ a$n.useEffect(() => {
22951
+ if (initialColumnFilters.current.length > 0) {
22952
+ onFilterChange?.(initialColumnFilters.current);
22953
+ }
22954
+ }, []);
22919
22955
  const isMounted = a$n.useRef(false);
22920
22956
  a$n.useEffect(() => {
22921
22957
  if (!isMounted.current) {
@@ -22925,8 +22961,9 @@ function Table({ columns, data, isLoading, serverSide = false, onPageChange, onS
22925
22961
  resetTable();
22926
22962
  }, [resetTrigger]);
22927
22963
  const resetTable = () => {
22928
- setColumnFilters(staticFilters ?? []);
22929
- setFilters({});
22964
+ const resetFilters = staticFilters ?? [];
22965
+ setColumnFilters(resetFilters);
22966
+ onFilterChange?.(resetFilters);
22930
22967
  setSorting([]);
22931
22968
  setPageIndex(1);
22932
22969
  setPagination({
@@ -22935,6 +22972,8 @@ function Table({ columns, data, isLoading, serverSide = false, onPageChange, onS
22935
22972
  });
22936
22973
  table.toggleAllRowsSelected(false);
22937
22974
  };
22975
+ const hasActiveFilters = Object.keys(filters).length > (staticFilters?.length ?? 0) &&
22976
+ Object.values(filters).some((v) => v?.length);
22938
22977
  return (a$n.createElement(a$n.Fragment, null,
22939
22978
  !isLoading && (a$n.createElement(ActionBar, null,
22940
22979
  a$n.createElement(GlobalActionWrapper, null, globalActions?.(table)),
@@ -22999,7 +23038,8 @@ function Table({ columns, data, isLoading, serverSide = false, onPageChange, onS
22999
23038
  }, key: index + "loading-row" }, Array.from({
23000
23039
  length: 10,
23001
23040
  }).map((_, i) => (a$n.createElement(LoadingShimmer, { key: `${i}-loading`, "$width": "110px", "$height": "25px" }))))))))) : (a$n.createElement(StyledTable, { id: `${id}-table`, ...htmlProps },
23002
- a$n.createElement("thead", null, table.getHeaderGroups().map((headerGroup) => (a$n.createElement(HeaderRow, { key: headerGroup.id, "$isEmpty": table.getRowModel().rows.length === 0 }, headerGroup.headers.map((header, i) => {
23041
+ a$n.createElement("thead", null, table.getHeaderGroups().map((headerGroup) => (a$n.createElement(HeaderRow, { key: headerGroup.id, "$isEmpty": table.getCoreRowModel().rows.length === 0 &&
23042
+ !hasActiveFilters }, headerGroup.headers.map((header, i) => {
23003
23043
  return (a$n.createElement(TableHeaderCell, { key: header.id, serverSide: serverSide, header: header, filters: filters, sorting: sorting, scrollPosition: scrollState, onFilterMenuInteraction: (id, active) => {
23004
23044
  setFilterMenuOpen((prev) => ({
23005
23045
  ...prev,
@@ -23014,14 +23054,21 @@ function Table({ columns, data, isLoading, serverSide = false, onPageChange, onS
23014
23054
  } }));
23015
23055
  }))))),
23016
23056
  a$n.createElement("tbody", null,
23017
- table.getRowModel().rows.length === 0 && (a$n.createElement(EmptyTableState, { header: emptyTableState?.header || "No data available.", subHeader: emptyTableState?.subHeader, showClearFilterButton: emptyTableState?.showClearFilterButton, onClearFilters: resetTable, colSpan: table.getVisibleLeafColumns().length, size: "large" })),
23057
+ table.getRowModel().rows.length === 0 && (a$n.createElement(EmptyTableState, { header: hasActiveFilters
23058
+ ? "No results found."
23059
+ : emptyTableState?.header || "No data available.", subHeader: !hasActiveFilters ? emptyTableState?.subHeader : undefined, showClearFilterButton: hasActiveFilters, onClearFilters: () => {
23060
+ resetTable();
23061
+ emptyTableState?.onClearFilters?.();
23062
+ }, colSpan: table.getVisibleLeafColumns().length, size: "large" })),
23018
23063
  table.getRowModel().rows.map((row) => (a$n.createElement(a$n.Fragment, { key: row.id },
23019
23064
  a$n.createElement(CellRow, { onClick: () => {
23065
+ if (showSelection)
23066
+ row.toggleSelected();
23020
23067
  if (!showExpandedRowToggle &&
23021
23068
  !!renderExpandedRow?.(row))
23022
23069
  toggleRowExpanded(row.id);
23023
23070
  onRowClick?.(row.original);
23024
- }, "$isClickable": !!onRowClick }, row.getVisibleCells().map((cell) => {
23071
+ }, "$isClickable": !!onRowClick || showSelection }, row.getVisibleCells().map((cell) => {
23025
23072
  const value = flexRender(cell.column.columnDef.cell, {
23026
23073
  ...cell.getContext(),
23027
23074
  localValue: rowState[row.id]?.[cell.column.id],