@majoo-ui/react 2.2.1 → 2.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.
@@ -12,7 +12,7 @@ import Flex from '../../layout/flex/Flex.esm.js';
12
12
  import { Grid, GridItem } from '../../layout/grid/Grid.esm.js';
13
13
  import Collapalse from './transition.esm.js';
14
14
  import { TableHeaderCellContainer, TableHeadCellContent } from '../table/Table.esm.js';
15
- import { useTranslation } from 'react-i18next';
15
+ import { defaultTableLocaleText } from '../table/locale.esm.js';
16
16
 
17
17
  const TableContainer = styled('div', {
18
18
  display: 'block',
@@ -101,7 +101,8 @@ function EditableTableMobile(props) {
101
101
  onExpand,
102
102
  hiddenColumns,
103
103
  customEmptyDataProps,
104
- virtualized
104
+ virtualized,
105
+ sortColumnTitle = defaultTableLocaleText.sortColumnTitle
105
106
  } = props;
106
107
  const {
107
108
  getTableProps,
@@ -113,9 +114,6 @@ function EditableTableMobile(props) {
113
114
  toggleAllRowsExpanded,
114
115
  setHiddenColumns
115
116
  } = instance;
116
- const {
117
- t
118
- } = useTranslation('MajooUI/table');
119
117
  useEffect(() => {
120
118
  if (hiddenColumns === null || hiddenColumns === void 0 ? void 0 : hiddenColumns.length) {
121
119
  setHiddenColumns(hiddenColumns);
@@ -275,7 +273,7 @@ function EditableTableMobile(props) {
275
273
  const isSelector = (column === null || column === void 0 ? void 0 : column.id) === 'selection';
276
274
  const headerRender = column.render('Header');
277
275
  return (isMobileHeader || isSelector) && (/*#__PURE__*/createElement(TableHeadCell, Object.assign({}, column.getHeaderProps(props => [props, column.sortable ? column.getSortByToggleProps({
278
- title: t('sortColumnTitle', 'Urutkan') || 'Urutkan'
276
+ title: sortColumnTitle
279
277
  }) : {
280
278
  onClick: column.onToggle
281
279
  }, {
@@ -15,9 +15,9 @@ import InputCheckbox from '../form/components/InputCheckbox/InputCheckbox.esm.js
15
15
  import Flex from '../../layout/flex/Flex.esm.js';
16
16
  import useMediaQuery from '../../utils/useMediaQuery.esm.js';
17
17
  import EditableTableMobile from './EditableMobile.esm.js';
18
- import { useTranslation } from 'react-i18next';
19
18
  import { pick, isEqual } from 'lodash';
20
19
  import { defaultEmptyDataProps, TableHeaderCellContainer, TableHeadCellContent } from '../table/Table.esm.js';
20
+ import { useTableLocaleText } from '../table/locale.esm.js';
21
21
  import { useVirtual } from 'react-virtual';
22
22
  import Tooltip from '../tooltip/Tooltip.esm.js';
23
23
 
@@ -309,11 +309,10 @@ function EditableTable(props) {
309
309
  hiddenColumns,
310
310
  customEmptyDataProps: emptyDataProps,
311
311
  virtualized = false,
312
- onSortByChange
312
+ onSortByChange,
313
+ localeText
313
314
  } = props;
314
- const {
315
- t
316
- } = useTranslation('MajooUI/table');
315
+ const tableLocaleText = useTableLocaleText(localeText);
317
316
  const [selectedIndex, setSelectedIndex] = useState(null);
318
317
  const isMobile = useMediaQuery(isMobileLayout === undefined ? '(max-width: 767px)' : isMobileLayout ? '(max-width: 8000px)' : '(max-width: 0px)');
319
318
  const IndeterminateCheckbox = props => {
@@ -403,7 +402,7 @@ function EditableTable(props) {
403
402
  });
404
403
  }
405
404
  }, [selectedRowIds, data, onSelectedChange, selectedIndex]);
406
- const customEmptyDataProps = emptyDataProps || defaultEmptyDataProps(t, isMobile);
405
+ const customEmptyDataProps = emptyDataProps || defaultEmptyDataProps(tableLocaleText, isMobile);
407
406
  const getCustomRows = (row, renderRow) => {
408
407
  var _a;
409
408
  let customStyle = {};
@@ -473,7 +472,7 @@ function EditableTable(props) {
473
472
  children: visibleHeaders.map(column => {
474
473
  const headerRender = column.render('Header');
475
474
  return !(column === null || column === void 0 ? void 0 : column.isMobileOnly) && jsx(TableHeadCell, Object.assign({}, column.getHeaderProps(props => [props, column.sortable ? column.getSortByToggleProps({
476
- title: t('sortColumnTitle', 'Urutkan') || 'Urutkan'
475
+ title: tableLocaleText.sortColumnTitle
477
476
  }) : {
478
477
  onClick: column.onToggle
479
478
  }, {
@@ -597,6 +596,7 @@ function EditableTable(props) {
597
596
  onExpand: onExpand,
598
597
  hiddenColumns: hiddenColumns,
599
598
  customEmptyDataProps: customEmptyDataProps,
599
+ sortColumnTitle: tableLocaleText.sortColumnTitle,
600
600
  virtualized: virtualized,
601
601
  rowVirtualizer: rowVirtualizer,
602
602
  tableContainerRef: tableContainerRef
@@ -437,7 +437,10 @@ const InputSelect = /*#__PURE__*/React.forwardRef((_a, ref) => {
437
437
  return setItem(options);
438
438
  } else {
439
439
  setItem(options.filter(item => {
440
- const nameIsIncluded = item.name.toLowerCase().includes(value.toLocaleLowerCase());
440
+ var _a;
441
+ // textSelector can point at a non-string field (numeric id, null), so never
442
+ // assume item.name is a string here.
443
+ const nameIsIncluded = String((_a = item.name) !== null && _a !== void 0 ? _a : '').toLowerCase().includes(value.toLocaleLowerCase());
441
444
  if (item.render && isFunction(item.render)) {
442
445
  const extractedString = item.render() ? extractStringFromHTML(renderToString(item.render())).join(',') : '';
443
446
  return nameIsIncluded || extractedString.toLowerCase().includes(value.toLocaleLowerCase());
@@ -532,12 +535,23 @@ const InputSelect = /*#__PURE__*/React.forwardRef((_a, ref) => {
532
535
  return addedGroupItems;
533
536
  }, []));
534
537
  }, [item]);
535
- const stateReducer = (_, changes) => {
538
+ const stateReducer = (state, changes) => {
536
539
  switch (changes.type) {
537
540
  case Downshift.stateChangeTypes.blurButton:
538
541
  return {
539
542
  isOpen: true
540
543
  };
544
+ // Downshift wipes selectedItem on Escape whenever its own isOpen is already false,
545
+ // firing onChange(null) on consumers that never asked to clear the selection.
546
+ // Escape only closes the menu and restores the label of the current selection.
547
+ case Downshift.stateChangeTypes.keyDownEscape:
548
+ {
549
+ const nextChanges = Object.assign(Object.assign({}, changes), {
550
+ inputValue: state.selectedItem ? state.selectedItem.name : ''
551
+ });
552
+ delete nextChanges.selectedItem;
553
+ return nextChanges;
554
+ }
541
555
  default:
542
556
  return changes;
543
557
  }
@@ -18,7 +18,7 @@ import Text from '../text/Text.esm.js';
18
18
  import { ConditionalWrapper } from '../../wrapper/ConditionalWrapper.esm.js';
19
19
  import { ContextMenuTrigger } from '../contextMenu/ContextMenu.esm.js';
20
20
  import Paragraph from '../paragraph/Paragraph.esm.js';
21
- import { useTranslation } from 'react-i18next';
21
+ import { defaultTableLocaleText } from './locale.esm.js';
22
22
 
23
23
  const TableContainer = styled(Flex, {
24
24
  position: 'relative',
@@ -88,12 +88,10 @@ const MobileTable = /*#__PURE__*/React__default.forwardRef(({
88
88
  footerData,
89
89
  footerColumnIds,
90
90
  headerRowSpan,
91
- keyId = 'id'
91
+ keyId = 'id',
92
+ sortColumnTitle = defaultTableLocaleText.sortColumnTitle
92
93
  }, ref) => {
93
94
  var _a, _b, _c, _d;
94
- const {
95
- t
96
- } = useTranslation('MajooUI/table');
97
95
  const {
98
96
  getTableProps,
99
97
  getTableBodyProps,
@@ -190,7 +188,7 @@ const MobileTable = /*#__PURE__*/React__default.forwardRef(({
190
188
  children: headerGroup.headers.filter((column, index) => filterMobileHeader(column, index)).map(column => {
191
189
  const headerRender = column.render('Header');
192
190
  return jsx(TableHeadCell, Object.assign({}, column.getHeaderProps(isHeaderSortable(column) ? column.getSortByToggleProps({
193
- title: t('sortColumnTitle', 'Urutkan') || 'Urutkan'
191
+ title: sortColumnTitle
194
192
  }) : {
195
193
  onClick: column.onToggle
196
194
  }), {
@@ -44,8 +44,8 @@ import { alignCss, headerAlignCss, resolveCellCss } from './utils/columnStyles.e
44
44
  import { footerValueOf } from './utils/footerValue.esm.js';
45
45
  import { HeaderTooltip } from './utils/HeaderTooltip.esm.js';
46
46
  import { isHeaderSortable, getAriaSort } from './utils/headerSort.esm.js';
47
+ import { useTableLocaleText, i18nTableLocaleText } from './locale.esm.js';
47
48
  import { useSticky, getStickyValue, getMarginRight } from 'react-table-sticky';
48
- import { useTranslation } from 'react-i18next';
49
49
  import { useVirtual } from 'react-virtual';
50
50
  import { PlusPrimitive } from '@majoo-ui/icons';
51
51
  import '../scrollSync/ScrollSync.esm.js';
@@ -524,9 +524,9 @@ const formattingData = (rawData, rowGroup) => {
524
524
  }
525
525
  return rawData;
526
526
  };
527
- const defaultEmptyDataProps = (t, isMobile) => ({
527
+ const emptyStateProps = (asset, title, description, isMobile) => ({
528
528
  doodleImage: jsx(TableEmptyStateDoodle, {
529
- asset: "emptyData",
529
+ asset: asset,
530
530
  "aria-hidden": "true"
531
531
  }),
532
532
  title: jsx(Paragraph, {
@@ -536,48 +536,31 @@ const defaultEmptyDataProps = (t, isMobile) => ({
536
536
  css: {
537
537
  marginTop: isMobile ? 0 : '$spacing-05'
538
538
  },
539
- children: t('dataNotAvailableTitle', 'Data tidak tersedia')
539
+ children: title
540
540
  }),
541
- description: !isMobile ? jsxs(Paragraph, {
541
+ description: !isMobile ? jsx(Paragraph, {
542
542
  paragraph: "shortContentRegular",
543
543
  color: "secondary",
544
544
  align: "center",
545
- children: [t('dataNotAvailableDescription_1', 'Belum ada data yang dapat ditampilkan'), ' ', t('dataNotAvailableDescription_2', 'di halaman ini')]
546
- }) : jsxs(Text, {
545
+ children: description
546
+ }) : jsx(Text, {
547
547
  variant: "caption",
548
548
  color: "secondary",
549
549
  align: "center",
550
- children: [t('dataNotAvailableDescription_1', 'Belum ada data yang dapat ditampilkan'), jsx("br", {}), t('dataNotAvailableDescription_2', 'di halaman ini')]
551
- })
552
- });
553
- const defaultEmptySearchProps = (t, isMobile, query) => ({
554
- doodleImage: jsx(TableEmptyStateDoodle, {
555
- asset: "emptySearchData",
556
- "aria-hidden": "true"
557
- }),
558
- title: jsx(Paragraph, {
559
- paragraph: "shortContentBold",
560
- color: "primary",
561
- align: "center",
562
- css: {
563
- marginTop: isMobile ? 0 : '$spacing-05'
564
- },
565
- children: t('dataNotAvailableTitleSearch', `Oops... ${query} tidak ditemukan`, {
566
- query
567
- })
568
- }),
569
- description: !isMobile ? jsxs(Paragraph, {
570
- paragraph: "shortContentRegular",
571
- color: "secondary",
572
- align: "center",
573
- children: [t('dataNotAvailableDescriptionSearch_1', 'Coba lagi dengan memasukkan'), ' ', t('dataNotAvailableDescriptionSearch_2', 'kata kunci yang tepat')]
574
- }) : jsxs(Text, {
575
- variant: "caption",
576
- color: "secondary",
577
- align: "center",
578
- children: [t('dataNotAvailableDescriptionSearch_1', 'Coba lagi dengan memasukkan'), jsx("br", {}), t('dataNotAvailableDescriptionSearch_2', 'kata kunci yang tepat')]
550
+ children: description
579
551
  })
580
552
  });
553
+ /**
554
+ * Builds the default empty state from resolved table texts.
555
+ * Passing an i18next `t` function as the first argument is deprecated.
556
+ */
557
+ const defaultEmptyDataProps = (localeText, isMobile) => {
558
+ const text = typeof localeText === 'function' ? i18nTableLocaleText(localeText) : localeText;
559
+ return emptyStateProps('emptyData', text.emptyDataTitle, text.emptyDataDescription, isMobile);
560
+ };
561
+ const defaultEmptySearchProps = (localeText, isMobile, query) => emptyStateProps('emptySearchData', localeText.emptySearchTitle({
562
+ query
563
+ }), localeText.emptySearchDescription, isMobile);
581
564
  function HeaderMenuOption(props) {
582
565
  const {
583
566
  open,
@@ -587,7 +570,8 @@ function HeaderMenuOption(props) {
587
570
  headerGroups,
588
571
  id,
589
572
  filterHeader: items,
590
- rowData
573
+ rowData,
574
+ title
591
575
  } = props;
592
576
  const {
593
577
  headers = []
@@ -601,7 +585,7 @@ function HeaderMenuOption(props) {
601
585
  asChild: true,
602
586
  children: children
603
587
  }), jsx(ModalDialogTitle, {
604
- children: "Tampilkan Kolom"
588
+ children: title
605
589
  }), jsx(ModalDialogContent, {
606
590
  css: {
607
591
  overflowY: visibleHeaders.filter(val => typeof val.Header === 'string').length > 8 ? 'scroll' : 'none'
@@ -710,8 +694,9 @@ function Table({
710
694
  fetchData,
711
695
  hideDataInfo = false,
712
696
  rowsPerPageOptions = [10, 25, 50, 100],
713
- emptyDataMessage = 'Tidak ada data',
697
+ localeText,
714
698
  customEmptyDataProps: emptyDataProps,
699
+ customEmptySearchProps: emptySearchProps,
715
700
  isLoading = false,
716
701
  css,
717
702
  headerCss,
@@ -766,11 +751,11 @@ function Table({
766
751
  const [filteredHeader, setFilteredHeader] = useState([]);
767
752
  const [hasDarkParent, setHasDarkParent] = useState(false);
768
753
  const [hoveredRowId, setHoveredRowId] = useState(null);
769
- const {
770
- t
771
- } = useTranslation('MajooUI/table');
754
+ const tableLocaleText = useTableLocaleText(paginationLabel && {
755
+ pagination: paginationLabel
756
+ }, localeText);
772
757
  const isMobile = useMediaQuery(isMobileLayout === undefined ? '(max-width: 1024px)' : isMobileLayout ? '(max-width: 8000px)' : '(max-width: 0px)');
773
- const customEmptyDataProps = searchQuery ? defaultEmptySearchProps(t, isMobile, searchQuery) : emptyDataProps || defaultEmptyDataProps(t, isMobile);
758
+ const customEmptyDataProps = searchQuery ? emptySearchProps || defaultEmptySearchProps(tableLocaleText, isMobile, searchQuery) : emptyDataProps || defaultEmptyDataProps(tableLocaleText, isMobile);
774
759
  const getInitialState = () => {
775
760
  const initialState = {};
776
761
  if (fetchData) {
@@ -903,56 +888,37 @@ function Table({
903
888
  });
904
889
  if (fetchData) fetchData(fetchParams);
905
890
  };
906
- const renderFooter = () => {
907
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
908
- return jsx(Pagination, {
909
- hidePagination: hidePagination || isExpandableTree,
910
- hideInputPageSection: false,
911
- limit: pageSize,
912
- currentPage: pageIndex + 1,
913
- totalData: totalData,
914
- totalPage: totalPage,
915
- onLimitChange: selectedItem => {
916
- if (selectedItem) {
917
- // always reset page when limit changed
918
- gotoPage(0);
919
- doFetchData(0, selectedItem);
920
- setPageSize(selectedItem);
921
- setLimit(selectedItem);
922
- }
923
- },
924
- hideDataInfo: hideDataInfo || isExpandableTree,
925
- onPageChange: page => {
926
- doFetchData(page - 1, pageSize);
927
- gotoPage(page - 1);
928
- },
929
- rowsPerPageOptions: rowsPerPageOptions,
930
- showingText: (_a = paginationLabel === null || paginationLabel === void 0 ? void 0 : paginationLabel.showingText) !== null && _a !== void 0 ? _a : t('pagination.showingText', 'Tampilkan:'),
931
- showingCountText: (_b = paginationLabel === null || paginationLabel === void 0 ? void 0 : paginationLabel.showingCountText) !== null && _b !== void 0 ? _b : ({
932
- from,
933
- to,
934
- total
935
- }) => t('pagination.showingCountText', `Ditampilkan ${from} - ${to} dari ${total} data`, {
936
- from,
937
- to,
938
- total
939
- }),
940
- dialogShowingText: (_c = paginationLabel === null || paginationLabel === void 0 ? void 0 : paginationLabel.dialogShowingText) !== null && _c !== void 0 ? _c : t('pagination.dialogShowingText', 'Tampilkan Data'),
941
- previousButton: (_d = paginationLabel === null || paginationLabel === void 0 ? void 0 : paginationLabel.previousButton) !== null && _d !== void 0 ? _d : t('pagination.previousButton', 'Sebelumnya'),
942
- nextButton: (_e = paginationLabel === null || paginationLabel === void 0 ? void 0 : paginationLabel.nextButton) !== null && _e !== void 0 ? _e : t('pagination.nextButton', 'Selanjutnya'),
943
- gotoPageText: (_f = paginationLabel === null || paginationLabel === void 0 ? void 0 : paginationLabel.gotoPageText) !== null && _f !== void 0 ? _f : t('pagination.gotoPageText', 'Ke Halaman'),
944
- goToPagePlaceholder: (_g = paginationLabel === null || paginationLabel === void 0 ? void 0 : paginationLabel.goToPagePlaceholder) !== null && _g !== void 0 ? _g : t('pagination.goToPagePlaceholder', 'Contoh: 10'),
945
- btnCancelText: (_h = paginationLabel === null || paginationLabel === void 0 ? void 0 : paginationLabel.btnCancelText) !== null && _h !== void 0 ? _h : t('pagination.btnCancelText', 'Batal'),
946
- btnSubmitText: (_j = paginationLabel === null || paginationLabel === void 0 ? void 0 : paginationLabel.btnSubmitText) !== null && _j !== void 0 ? _j : t('pagination.btnSubmitText', 'Lanjutkan'),
947
- css: {
948
- backgroundColor: '$bgWhite',
949
- padding: '$spacing-04 0',
950
- '@md': {
951
- padding: '$spacing-06 $spacing-03'
952
- }
891
+ const renderFooter = () => jsx(Pagination, Object.assign({
892
+ hidePagination: hidePagination || isExpandableTree,
893
+ hideInputPageSection: false,
894
+ limit: pageSize,
895
+ currentPage: pageIndex + 1,
896
+ totalData: totalData,
897
+ totalPage: totalPage,
898
+ onLimitChange: selectedItem => {
899
+ if (selectedItem) {
900
+ // always reset page when limit changed
901
+ gotoPage(0);
902
+ doFetchData(0, selectedItem);
903
+ setPageSize(selectedItem);
904
+ setLimit(selectedItem);
953
905
  }
954
- });
955
- };
906
+ },
907
+ hideDataInfo: hideDataInfo || isExpandableTree,
908
+ onPageChange: page => {
909
+ doFetchData(page - 1, pageSize);
910
+ gotoPage(page - 1);
911
+ },
912
+ rowsPerPageOptions: rowsPerPageOptions
913
+ }, tableLocaleText.pagination, {
914
+ css: {
915
+ backgroundColor: '$bgWhite',
916
+ padding: '$spacing-04 0',
917
+ '@md': {
918
+ padding: '$spacing-06 $spacing-03'
919
+ }
920
+ }
921
+ }));
956
922
  const renderInfiniteScrollWrapper = children => jsx(ConditionalWrapper, {
957
923
  condition: isInfiniteScroll && rawData.length > 0,
958
924
  wrapper: children => jsx(InfiniteScroll, {
@@ -1059,7 +1025,7 @@ function Table({
1059
1025
  children: visibleHeaders.map((column, index) => {
1060
1026
  const headerRender = column.render('Header');
1061
1027
  return jsx(TableHeadCell, Object.assign({}, column.getHeaderProps(props => [props, isHeaderSortable(column) ? column.getSortByToggleProps({
1062
- title: t('sortColumnTitle', 'Urutkan') || 'Urutkan'
1028
+ title: tableLocaleText.sortColumnTitle
1063
1029
  }) : {
1064
1030
  onClick: column.onToggle
1065
1031
  }, {
@@ -1303,7 +1269,7 @@ function Table({
1303
1269
  }, index) => {
1304
1270
  const headerRender = column.render('Header');
1305
1271
  return jsx(TableHeadCell, Object.assign({}, column.getHeaderProps(props => [props, isHeaderSortable(column) ? column.getSortByToggleProps({
1306
- title: t('sortColumnTitle', 'Urutkan') || 'Urutkan'
1272
+ title: tableLocaleText.sortColumnTitle
1307
1273
  }) : {
1308
1274
  onClick: column.onToggle
1309
1275
  }, {
@@ -1621,6 +1587,7 @@ function Table({
1621
1587
  onChange: handleFilterHeaderChange,
1622
1588
  headerGroups: headerGroups,
1623
1589
  filterHeader: filterHeader,
1590
+ title: tableLocaleText.showColumnTitle,
1624
1591
  children: jsx(IconButton, {
1625
1592
  css: {
1626
1593
  zIndex: '$docked',
@@ -1695,7 +1662,8 @@ function Table({
1695
1662
  footerData: footerData,
1696
1663
  footerColumnIds: (footerData === null || footerData === void 0 ? void 0 : footerData.length) ? new Set(visibleColumns.filter(column => column.Footer !== emptyRenderer).map(column => column.id)) : undefined,
1697
1664
  headerRowSpan: headerRowSpan,
1698
- keyId: keyId
1665
+ keyId: keyId,
1666
+ sortColumnTitle: tableLocaleText.sortColumnTitle
1699
1667
  })]
1700
1668
  });
1701
1669
  }
@@ -3,7 +3,6 @@ import 'core-js/modules/es.iterator.map.js';
3
3
  import React__default, { useState } from 'react';
4
4
  import { EllipsisHorizontalOutline } from '@majoo-ui/icons';
5
5
  import Box from '../../../../layout/box/Box.esm.js';
6
- import { useTranslation } from 'react-i18next';
7
6
  import { jsxs, jsx } from 'react/jsx-runtime';
8
7
  import { DropdownMenu, DropdownMenuTrigger, DropdownMenuPortal, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator } from '../../../dropdownMenu/DropdownMenu.esm.js';
9
8
  import IconButton from '../../../iconButton/IconButton.esm.js';
@@ -13,11 +12,7 @@ const rowMenuColumn = (options, icon, config) => ({
13
12
  options,
14
13
  Header: () => null,
15
14
  Cell: props => {
16
- const {
17
- t
18
- } = useTranslation('MajooUI/table');
19
15
  const defaultConfig = {
20
- mobileTitle: t('rowMenuMobileLabel', 'Aksi'),
21
16
  cssContent: {},
22
17
  cssMenuItem: {},
23
18
  align: 'end'
@@ -0,0 +1,91 @@
1
+ import 'core-js/modules/es.iterator.constructor.js';
2
+ import 'core-js/modules/es.iterator.filter.js';
3
+ import 'core-js/modules/es.iterator.reduce.js';
4
+ import { useContext, useMemo } from 'react';
5
+ import { useTranslation } from 'react-i18next';
6
+ import { LocaleTextContext } from '../../config/locale/LocaleTextContext.esm.js';
7
+
8
+ const defaultTableLocaleText = {
9
+ sortColumnTitle: 'Urutkan',
10
+ showColumnTitle: 'Tampilkan Kolom',
11
+ emptyDataTitle: 'Data tidak tersedia',
12
+ emptyDataDescription: 'Belum ada data yang dapat ditampilkan di halaman ini',
13
+ emptySearchTitle: ({
14
+ query
15
+ }) => `Oops... ${query} tidak ditemukan`,
16
+ emptySearchDescription: 'Coba lagi dengan memasukkan kata kunci yang tepat',
17
+ pagination: {
18
+ showingText: 'Tampilkan:',
19
+ showingCountText: ({
20
+ from,
21
+ to,
22
+ total
23
+ }) => `Ditampilkan ${from} - ${to} dari ${total} data`,
24
+ dialogShowingText: 'Tampilkan Data',
25
+ previousButton: 'Sebelumnya',
26
+ nextButton: 'Selanjutnya',
27
+ gotoPageText: 'Ke Halaman',
28
+ goToPagePlaceholder: 'Contoh: 10',
29
+ btnCancelText: 'Batal',
30
+ btnSubmitText: 'Lanjutkan'
31
+ }
32
+ };
33
+ // Transitional: keeps apps that still ship `MajooUI/table` locale files translated until they pass
34
+ // `localeText`. Remove together with the react-i18next dependency of the table family.
35
+ const i18nTableLocaleText = t => {
36
+ const d = defaultTableLocaleText;
37
+ return {
38
+ sortColumnTitle: t('sortColumnTitle', d.sortColumnTitle),
39
+ showColumnTitle: t('customColumnTitle', d.showColumnTitle),
40
+ emptyDataTitle: t('dataNotAvailableTitle', d.emptyDataTitle),
41
+ emptyDataDescription: `${t('dataNotAvailableDescription_1', 'Belum ada data yang dapat ditampilkan')} ${t('dataNotAvailableDescription_2', 'di halaman ini')}`,
42
+ emptySearchTitle: ({
43
+ query
44
+ }) => t('dataNotAvailableTitleSearch', `Oops... ${query} tidak ditemukan`, {
45
+ query
46
+ }),
47
+ emptySearchDescription: `${t('dataNotAvailableDescriptionSearch_1', 'Coba lagi dengan memasukkan')} ${t('dataNotAvailableDescriptionSearch_2', 'kata kunci yang tepat')}`,
48
+ pagination: {
49
+ showingText: t('pagination.showingText', d.pagination.showingText),
50
+ showingCountText: ({
51
+ from,
52
+ to,
53
+ total
54
+ }) => t('pagination.showingCountText', `Ditampilkan ${from} - ${to} dari ${total} data`, {
55
+ from,
56
+ to,
57
+ total
58
+ }),
59
+ dialogShowingText: t('pagination.dialogShowingText', d.pagination.dialogShowingText),
60
+ previousButton: t('pagination.previousButton', d.pagination.previousButton),
61
+ nextButton: t('pagination.nextButton', d.pagination.nextButton),
62
+ gotoPageText: t('pagination.gotoPageText', d.pagination.gotoPageText),
63
+ goToPagePlaceholder: t('pagination.goToPagePlaceholder', d.pagination.goToPagePlaceholder),
64
+ btnCancelText: t('pagination.btnCancelText', d.pagination.btnCancelText),
65
+ btnSubmitText: t('pagination.btnSubmitText', d.pagination.btnSubmitText)
66
+ }
67
+ };
68
+ };
69
+ const definedEntries = obj => obj ? Object.fromEntries(Object.entries(obj).filter(([, value]) => value !== undefined)) : {};
70
+ /** Later sources win; an `undefined` value never erases an earlier one. */
71
+ const mergeTableLocaleText = (base, ...overrides) => overrides.reduce((merged, override) => Object.assign(Object.assign(Object.assign({}, merged), definedEntries(override)), {
72
+ pagination: Object.assign(Object.assign({}, merged.pagination), definedEntries(override === null || override === void 0 ? void 0 : override.pagination))
73
+ }), base);
74
+ /**
75
+ * Resolves the table texts. Precedence: the table's own `localeText`, then `MajooProvider`'s
76
+ * `localeText.table`, then the app's `MajooUI/table` translations, then the Indonesian defaults.
77
+ * Several table-level overrides may be passed; later ones win. Pass the same number on every render.
78
+ */
79
+ const useTableLocaleText = (...localeTexts) => {
80
+ const {
81
+ t
82
+ } = useTranslation('MajooUI/table');
83
+ const {
84
+ table: appLocaleText
85
+ } = useContext(LocaleTextContext);
86
+ return useMemo(() => mergeTableLocaleText(i18nTableLocaleText(t), appLocaleText, ...localeTexts),
87
+ // eslint-disable-next-line react-hooks/exhaustive-deps
88
+ [t, appLocaleText, ...localeTexts]);
89
+ };
90
+
91
+ export { defaultTableLocaleText, i18nTableLocaleText, mergeTableLocaleText, useTableLocaleText };
@@ -0,0 +1,5 @@
1
+ import * as React from 'react';
2
+
3
+ const LocaleTextContext = /*#__PURE__*/React.createContext({});
4
+
5
+ export { LocaleTextContext };
package/index.esm.css CHANGED
@@ -1,252 +1,3 @@
1
- .recharts-pie-sector {
2
- outline: none;
3
- }
4
-
5
- .ReactCrop {
6
- position: relative;
7
- display: inline-block;
8
- cursor: crosshair;
9
- overflow: hidden;
10
- max-width: 100%;
11
- }
12
- .ReactCrop *,
13
- .ReactCrop *::before,
14
- .ReactCrop *::after {
15
- box-sizing: border-box;
16
- }
17
- .ReactCrop--disabled,
18
- .ReactCrop--locked {
19
- cursor: inherit;
20
- }
21
- .ReactCrop__child-wrapper {
22
- max-height: inherit;
23
- }
24
- .ReactCrop__child-wrapper > img,
25
- .ReactCrop__child-wrapper > video {
26
- display: block;
27
- max-width: 100%;
28
- max-height: inherit;
29
- touch-action: none;
30
- }
31
- .ReactCrop__crop-selection {
32
- position: absolute;
33
- top: 0;
34
- left: 0;
35
- transform: translate3d(0, 0, 0);
36
- cursor: move;
37
- box-shadow: 0 0 0 9999em rgba(0, 0, 0, 0.5);
38
- touch-action: none;
39
- border: 1px dashed #fff;
40
- }
41
- .ReactCrop--disabled .ReactCrop__crop-selection {
42
- cursor: inherit;
43
- }
44
- .ReactCrop--circular-crop .ReactCrop__crop-selection {
45
- border-radius: 50%;
46
- box-shadow: 0px 0px 1px 1px #fff, 0 0 0 9999em rgba(0, 0, 0, 0.5);
47
- }
48
- .ReactCrop__crop-selection:focus {
49
- outline: none;
50
- border-color: blue;
51
- border-style: solid;
52
- }
53
- .ReactCrop--invisible-crop .ReactCrop__crop-selection {
54
- display: none;
55
- }
56
- .ReactCrop__rule-of-thirds-vt::before,
57
- .ReactCrop__rule-of-thirds-vt::after,
58
- .ReactCrop__rule-of-thirds-hz::before,
59
- .ReactCrop__rule-of-thirds-hz::after {
60
- content: '';
61
- display: block;
62
- position: absolute;
63
- background-color: rgba(255, 255, 255, 0.4);
64
- }
65
- .ReactCrop__rule-of-thirds-vt::before,
66
- .ReactCrop__rule-of-thirds-vt::after {
67
- width: 1px;
68
- height: 100%;
69
- }
70
- .ReactCrop__rule-of-thirds-vt::before {
71
- left: 33.3333%;
72
- left: 33.3333333333%;
73
- }
74
- .ReactCrop__rule-of-thirds-vt::after {
75
- left: 66.6666%;
76
- left: 66.6666666667%;
77
- }
78
- .ReactCrop__rule-of-thirds-hz::before,
79
- .ReactCrop__rule-of-thirds-hz::after {
80
- width: 100%;
81
- height: 1px;
82
- }
83
- .ReactCrop__rule-of-thirds-hz::before {
84
- top: 33.3333%;
85
- top: 33.3333333333%;
86
- }
87
- .ReactCrop__rule-of-thirds-hz::after {
88
- top: 66.6666%;
89
- top: 66.6666666667%;
90
- }
91
- .ReactCrop__drag-handle {
92
- position: absolute;
93
- }
94
- .ReactCrop__drag-handle::after {
95
- position: absolute;
96
- content: '';
97
- display: block;
98
- width: 10px;
99
- height: 10px;
100
- background-color: rgba(0, 0, 0, 0.2);
101
- border: 1px solid rgba(255, 255, 255, 0.7);
102
- outline: 1px solid rgba(0, 0, 0, 0);
103
- }
104
- .ReactCrop__drag-handle:focus::after {
105
- border-color: blue;
106
- background: #2dbfff;
107
- }
108
- .ReactCrop .ord-nw {
109
- top: 0;
110
- left: 0;
111
- margin-top: -5px;
112
- margin-left: -5px;
113
- cursor: nw-resize;
114
- }
115
- .ReactCrop .ord-nw::after {
116
- top: 0;
117
- left: 0;
118
- }
119
- .ReactCrop .ord-n {
120
- top: 0;
121
- left: 50%;
122
- margin-top: -5px;
123
- margin-left: -5px;
124
- cursor: n-resize;
125
- }
126
- .ReactCrop .ord-n::after {
127
- top: 0;
128
- }
129
- .ReactCrop .ord-ne {
130
- top: 0;
131
- right: 0;
132
- margin-top: -5px;
133
- margin-right: -5px;
134
- cursor: ne-resize;
135
- }
136
- .ReactCrop .ord-ne::after {
137
- top: 0;
138
- right: 0;
139
- }
140
- .ReactCrop .ord-e {
141
- top: 50%;
142
- right: 0;
143
- margin-top: -5px;
144
- margin-right: -5px;
145
- cursor: e-resize;
146
- }
147
- .ReactCrop .ord-e::after {
148
- right: 0;
149
- }
150
- .ReactCrop .ord-se {
151
- bottom: 0;
152
- right: 0;
153
- margin-bottom: -5px;
154
- margin-right: -5px;
155
- cursor: se-resize;
156
- }
157
- .ReactCrop .ord-se::after {
158
- bottom: 0;
159
- right: 0;
160
- }
161
- .ReactCrop .ord-s {
162
- bottom: 0;
163
- left: 50%;
164
- margin-bottom: -5px;
165
- margin-left: -5px;
166
- cursor: s-resize;
167
- }
168
- .ReactCrop .ord-s::after {
169
- bottom: 0;
170
- }
171
- .ReactCrop .ord-sw {
172
- bottom: 0;
173
- left: 0;
174
- margin-bottom: -5px;
175
- margin-left: -5px;
176
- cursor: sw-resize;
177
- }
178
- .ReactCrop .ord-sw::after {
179
- bottom: 0;
180
- left: 0;
181
- }
182
- .ReactCrop .ord-w {
183
- top: 50%;
184
- left: 0;
185
- margin-top: -5px;
186
- margin-left: -5px;
187
- cursor: w-resize;
188
- }
189
- .ReactCrop .ord-w::after {
190
- left: 0;
191
- }
192
- .ReactCrop__disabled .ReactCrop__drag-handle {
193
- cursor: inherit;
194
- }
195
- .ReactCrop__drag-bar {
196
- position: absolute;
197
- }
198
- .ReactCrop__drag-bar.ord-n {
199
- top: 0;
200
- left: 0;
201
- width: 100%;
202
- height: 6px;
203
- margin-top: -3px;
204
- }
205
- .ReactCrop__drag-bar.ord-e {
206
- right: 0;
207
- top: 0;
208
- width: 6px;
209
- height: 100%;
210
- margin-right: -3px;
211
- }
212
- .ReactCrop__drag-bar.ord-s {
213
- bottom: 0;
214
- left: 0;
215
- width: 100%;
216
- height: 6px;
217
- margin-bottom: -3px;
218
- }
219
- .ReactCrop__drag-bar.ord-w {
220
- top: 0;
221
- left: 0;
222
- width: 6px;
223
- height: 100%;
224
- margin-left: -3px;
225
- }
226
- .ReactCrop--new-crop .ReactCrop__drag-bar,
227
- .ReactCrop--new-crop .ReactCrop__drag-handle,
228
- .ReactCrop--fixed-aspect .ReactCrop__drag-bar {
229
- display: none;
230
- }
231
- .ReactCrop--fixed-aspect .ReactCrop__drag-handle.ord-n,
232
- .ReactCrop--fixed-aspect .ReactCrop__drag-handle.ord-e,
233
- .ReactCrop--fixed-aspect .ReactCrop__drag-handle.ord-s,
234
- .ReactCrop--fixed-aspect .ReactCrop__drag-handle.ord-w {
235
- display: none;
236
- }
237
- @media (pointer: coarse) {
238
- .ReactCrop .ord-n,
239
- .ReactCrop .ord-e,
240
- .ReactCrop .ord-s,
241
- .ReactCrop .ord-w {
242
- display: none;
243
- }
244
- .ReactCrop__drag-handle {
245
- width: 24px;
246
- height: 24px;
247
- }
248
- }
249
-
250
1
  .rdw-option-wrapper {
251
2
  padding: 5px;
252
3
  min-width: 25px;
@@ -1293,3 +1044,252 @@
1293
1044
  .public-DraftStyleDefault-depth4.public-DraftStyleDefault-reset {
1294
1045
  counter-reset: ol4;
1295
1046
  }
1047
+
1048
+ .ReactCrop {
1049
+ position: relative;
1050
+ display: inline-block;
1051
+ cursor: crosshair;
1052
+ overflow: hidden;
1053
+ max-width: 100%;
1054
+ }
1055
+ .ReactCrop *,
1056
+ .ReactCrop *::before,
1057
+ .ReactCrop *::after {
1058
+ box-sizing: border-box;
1059
+ }
1060
+ .ReactCrop--disabled,
1061
+ .ReactCrop--locked {
1062
+ cursor: inherit;
1063
+ }
1064
+ .ReactCrop__child-wrapper {
1065
+ max-height: inherit;
1066
+ }
1067
+ .ReactCrop__child-wrapper > img,
1068
+ .ReactCrop__child-wrapper > video {
1069
+ display: block;
1070
+ max-width: 100%;
1071
+ max-height: inherit;
1072
+ touch-action: none;
1073
+ }
1074
+ .ReactCrop__crop-selection {
1075
+ position: absolute;
1076
+ top: 0;
1077
+ left: 0;
1078
+ transform: translate3d(0, 0, 0);
1079
+ cursor: move;
1080
+ box-shadow: 0 0 0 9999em rgba(0, 0, 0, 0.5);
1081
+ touch-action: none;
1082
+ border: 1px dashed #fff;
1083
+ }
1084
+ .ReactCrop--disabled .ReactCrop__crop-selection {
1085
+ cursor: inherit;
1086
+ }
1087
+ .ReactCrop--circular-crop .ReactCrop__crop-selection {
1088
+ border-radius: 50%;
1089
+ box-shadow: 0px 0px 1px 1px #fff, 0 0 0 9999em rgba(0, 0, 0, 0.5);
1090
+ }
1091
+ .ReactCrop__crop-selection:focus {
1092
+ outline: none;
1093
+ border-color: blue;
1094
+ border-style: solid;
1095
+ }
1096
+ .ReactCrop--invisible-crop .ReactCrop__crop-selection {
1097
+ display: none;
1098
+ }
1099
+ .ReactCrop__rule-of-thirds-vt::before,
1100
+ .ReactCrop__rule-of-thirds-vt::after,
1101
+ .ReactCrop__rule-of-thirds-hz::before,
1102
+ .ReactCrop__rule-of-thirds-hz::after {
1103
+ content: '';
1104
+ display: block;
1105
+ position: absolute;
1106
+ background-color: rgba(255, 255, 255, 0.4);
1107
+ }
1108
+ .ReactCrop__rule-of-thirds-vt::before,
1109
+ .ReactCrop__rule-of-thirds-vt::after {
1110
+ width: 1px;
1111
+ height: 100%;
1112
+ }
1113
+ .ReactCrop__rule-of-thirds-vt::before {
1114
+ left: 33.3333%;
1115
+ left: 33.3333333333%;
1116
+ }
1117
+ .ReactCrop__rule-of-thirds-vt::after {
1118
+ left: 66.6666%;
1119
+ left: 66.6666666667%;
1120
+ }
1121
+ .ReactCrop__rule-of-thirds-hz::before,
1122
+ .ReactCrop__rule-of-thirds-hz::after {
1123
+ width: 100%;
1124
+ height: 1px;
1125
+ }
1126
+ .ReactCrop__rule-of-thirds-hz::before {
1127
+ top: 33.3333%;
1128
+ top: 33.3333333333%;
1129
+ }
1130
+ .ReactCrop__rule-of-thirds-hz::after {
1131
+ top: 66.6666%;
1132
+ top: 66.6666666667%;
1133
+ }
1134
+ .ReactCrop__drag-handle {
1135
+ position: absolute;
1136
+ }
1137
+ .ReactCrop__drag-handle::after {
1138
+ position: absolute;
1139
+ content: '';
1140
+ display: block;
1141
+ width: 10px;
1142
+ height: 10px;
1143
+ background-color: rgba(0, 0, 0, 0.2);
1144
+ border: 1px solid rgba(255, 255, 255, 0.7);
1145
+ outline: 1px solid rgba(0, 0, 0, 0);
1146
+ }
1147
+ .ReactCrop__drag-handle:focus::after {
1148
+ border-color: blue;
1149
+ background: #2dbfff;
1150
+ }
1151
+ .ReactCrop .ord-nw {
1152
+ top: 0;
1153
+ left: 0;
1154
+ margin-top: -5px;
1155
+ margin-left: -5px;
1156
+ cursor: nw-resize;
1157
+ }
1158
+ .ReactCrop .ord-nw::after {
1159
+ top: 0;
1160
+ left: 0;
1161
+ }
1162
+ .ReactCrop .ord-n {
1163
+ top: 0;
1164
+ left: 50%;
1165
+ margin-top: -5px;
1166
+ margin-left: -5px;
1167
+ cursor: n-resize;
1168
+ }
1169
+ .ReactCrop .ord-n::after {
1170
+ top: 0;
1171
+ }
1172
+ .ReactCrop .ord-ne {
1173
+ top: 0;
1174
+ right: 0;
1175
+ margin-top: -5px;
1176
+ margin-right: -5px;
1177
+ cursor: ne-resize;
1178
+ }
1179
+ .ReactCrop .ord-ne::after {
1180
+ top: 0;
1181
+ right: 0;
1182
+ }
1183
+ .ReactCrop .ord-e {
1184
+ top: 50%;
1185
+ right: 0;
1186
+ margin-top: -5px;
1187
+ margin-right: -5px;
1188
+ cursor: e-resize;
1189
+ }
1190
+ .ReactCrop .ord-e::after {
1191
+ right: 0;
1192
+ }
1193
+ .ReactCrop .ord-se {
1194
+ bottom: 0;
1195
+ right: 0;
1196
+ margin-bottom: -5px;
1197
+ margin-right: -5px;
1198
+ cursor: se-resize;
1199
+ }
1200
+ .ReactCrop .ord-se::after {
1201
+ bottom: 0;
1202
+ right: 0;
1203
+ }
1204
+ .ReactCrop .ord-s {
1205
+ bottom: 0;
1206
+ left: 50%;
1207
+ margin-bottom: -5px;
1208
+ margin-left: -5px;
1209
+ cursor: s-resize;
1210
+ }
1211
+ .ReactCrop .ord-s::after {
1212
+ bottom: 0;
1213
+ }
1214
+ .ReactCrop .ord-sw {
1215
+ bottom: 0;
1216
+ left: 0;
1217
+ margin-bottom: -5px;
1218
+ margin-left: -5px;
1219
+ cursor: sw-resize;
1220
+ }
1221
+ .ReactCrop .ord-sw::after {
1222
+ bottom: 0;
1223
+ left: 0;
1224
+ }
1225
+ .ReactCrop .ord-w {
1226
+ top: 50%;
1227
+ left: 0;
1228
+ margin-top: -5px;
1229
+ margin-left: -5px;
1230
+ cursor: w-resize;
1231
+ }
1232
+ .ReactCrop .ord-w::after {
1233
+ left: 0;
1234
+ }
1235
+ .ReactCrop__disabled .ReactCrop__drag-handle {
1236
+ cursor: inherit;
1237
+ }
1238
+ .ReactCrop__drag-bar {
1239
+ position: absolute;
1240
+ }
1241
+ .ReactCrop__drag-bar.ord-n {
1242
+ top: 0;
1243
+ left: 0;
1244
+ width: 100%;
1245
+ height: 6px;
1246
+ margin-top: -3px;
1247
+ }
1248
+ .ReactCrop__drag-bar.ord-e {
1249
+ right: 0;
1250
+ top: 0;
1251
+ width: 6px;
1252
+ height: 100%;
1253
+ margin-right: -3px;
1254
+ }
1255
+ .ReactCrop__drag-bar.ord-s {
1256
+ bottom: 0;
1257
+ left: 0;
1258
+ width: 100%;
1259
+ height: 6px;
1260
+ margin-bottom: -3px;
1261
+ }
1262
+ .ReactCrop__drag-bar.ord-w {
1263
+ top: 0;
1264
+ left: 0;
1265
+ width: 6px;
1266
+ height: 100%;
1267
+ margin-left: -3px;
1268
+ }
1269
+ .ReactCrop--new-crop .ReactCrop__drag-bar,
1270
+ .ReactCrop--new-crop .ReactCrop__drag-handle,
1271
+ .ReactCrop--fixed-aspect .ReactCrop__drag-bar {
1272
+ display: none;
1273
+ }
1274
+ .ReactCrop--fixed-aspect .ReactCrop__drag-handle.ord-n,
1275
+ .ReactCrop--fixed-aspect .ReactCrop__drag-handle.ord-e,
1276
+ .ReactCrop--fixed-aspect .ReactCrop__drag-handle.ord-s,
1277
+ .ReactCrop--fixed-aspect .ReactCrop__drag-handle.ord-w {
1278
+ display: none;
1279
+ }
1280
+ @media (pointer: coarse) {
1281
+ .ReactCrop .ord-n,
1282
+ .ReactCrop .ord-e,
1283
+ .ReactCrop .ord-s,
1284
+ .ReactCrop .ord-w {
1285
+ display: none;
1286
+ }
1287
+ .ReactCrop__drag-handle {
1288
+ width: 24px;
1289
+ height: 24px;
1290
+ }
1291
+ }
1292
+
1293
+ .recharts-pie-sector {
1294
+ outline: none;
1295
+ }
package/index.esm.js CHANGED
@@ -42,6 +42,7 @@ export { NativeTimePicker, TimePicker } from './components/datePicker/timePicker
42
42
  export { InputTimePicker } from './components/datePicker/timePicker/InputTimePicker.esm.js';
43
43
  export { DatePickerMulti } from './components/datePicker/DatePickerMulti.esm.js';
44
44
  export { Cell, Table, TableBody, TableCell, TableColumn, TableContent, TableFoot, TableFootCell, TableFootRow, TableHead, TableHeadCellContent, TableHeaderCellContainer, TableRow, addOnCellStyle, defaultEmptyDataProps, defaultFetchDataParams } from './components/table/Table.esm.js';
45
+ export { defaultTableLocaleText } from './components/table/locale.esm.js';
45
46
  export { default as MobileTable } from './components/table/MobileTable.esm.js';
46
47
  export { PageDialog, PageDialogContent, PageDialogFooter, PageDialogTitle, PageDialogTrigger } from './components/pageDialog/PageDialog.esm.js';
47
48
  export { default as DevicePreview, ImageDevicePreview } from './components/devicePreview/DevicePreview.esm.js';
@@ -5,14 +5,17 @@ import { theme } from '../config/stitches.config.esm.js';
5
5
  import PropTypes from 'prop-types';
6
6
  import { useTranslation } from 'react-i18next';
7
7
  import moment from 'moment';
8
+ import { LocaleTextContext } from '../config/locale/LocaleTextContext.esm.js';
8
9
  import { jsx } from 'react/jsx-runtime';
9
10
 
11
+ const EMPTY_LOCALE_TEXT = {};
10
12
  function MajooProvider({
11
13
  children,
12
14
  name,
13
15
  theme: theme$1 = theme,
14
16
  extendStyle,
15
- disableGlobalStyle
17
+ disableGlobalStyle,
18
+ localeText = EMPTY_LOCALE_TEXT
16
19
  }) {
17
20
  !disableGlobalStyle && applyGlobalStyles(extendStyle, theme$1);
18
21
  const {
@@ -22,7 +25,10 @@ function MajooProvider({
22
25
  return /*#__PURE__*/jsx(ThemeProvider, {
23
26
  name: name,
24
27
  theme: theme$1,
25
- children: children
28
+ children: /*#__PURE__*/jsx(LocaleTextContext.Provider, {
29
+ value: localeText,
30
+ children: children
31
+ })
26
32
  });
27
33
  }
28
34
  MajooProvider.propTypes = {
@@ -30,7 +36,14 @@ MajooProvider.propTypes = {
30
36
  theme: PropTypes.object.isRequired,
31
37
  children: PropTypes.node.isRequired,
32
38
  extendStyle: PropTypes.object,
33
- disableGlobalStyle: PropTypes.bool
39
+ disableGlobalStyle: PropTypes.bool,
40
+ /**
41
+ * Component texts for the whole app, e.g. `{ table: { emptyDataTitle: 'No data' } }`.
42
+ * Memoize it: every new object re-renders all components that read it.
43
+ */
44
+ localeText: PropTypes.shape({
45
+ table: PropTypes.object
46
+ })
34
47
  };
35
48
  MajooProvider.defaultProps = {
36
49
  name: 'default',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@majoo-ui/react",
3
- "version": "2.2.1",
3
+ "version": "2.3.0",
4
4
  "main": "./index.esm.js",
5
5
  "sideEffects": [
6
6
  "*.css",
@@ -37,7 +37,7 @@
37
37
  "@floating-ui/react": "^0.19.2",
38
38
  "@majoo-ui/core": "1.32.0",
39
39
  "@majoo-ui/helpers": "1.30.9",
40
- "@majoo-ui/icons": "1.40.3",
40
+ "@majoo-ui/icons": "1.40.4",
41
41
  "@monsonjeremy/react-leaflet": "^3.2.2",
42
42
  "@radix-ui/react-accordion": "^1.0.0",
43
43
  "@radix-ui/react-alert-dialog": "^1.0.3",
@@ -18,6 +18,7 @@ interface EditableMobileProps<Data extends object> {
18
18
  hiddenColumns?: string[];
19
19
  customEmptyDataProps?: EmptyDataProps;
20
20
  virtualized?: boolean;
21
+ sortColumnTitle?: string;
21
22
  }
22
23
  export default function EditableTableMobile(props: EditableMobileProps<any>): JSX.Element;
23
24
  export {};
@@ -2,6 +2,7 @@ import React from 'react';
2
2
  import { Column, Row, SortingRule } from 'react-table';
3
3
  import { CSS } from '../../config/stitches.config';
4
4
  import { EmptyDataProps } from '../table/Table';
5
+ import { TableLocaleText } from '../table/locale';
5
6
  interface CustomRows {
6
7
  predicate: boolean;
7
8
  css?: CSS;
@@ -88,6 +89,11 @@ interface EditableTableProps<Data extends object> {
88
89
  * Sort by changes callback
89
90
  */
90
91
  onSortByChange?: (sortBy: SortingRule<object>[]) => void;
92
+ /**
93
+ * Texts of this table, same as `Table`'s `localeText`. Only `sortColumnTitle`, `emptyDataTitle`
94
+ * and `emptyDataDescription` apply.
95
+ */
96
+ localeText?: Partial<TableLocaleText>;
91
97
  }
92
98
  interface RemoveProps {
93
99
  position?: 'leftBottom' | 'rightBottom' | 'leftTop' | 'rightTop';
@@ -160,9 +166,7 @@ declare namespace EditableTable {
160
166
  }) => {
161
167
  marginBottom: {
162
168
  readonly [$$ScaleValue]: "space";
163
- }; /**
164
- * Additional height of the rows.
165
- */
169
+ };
166
170
  };
167
171
  ml: (value: {
168
172
  readonly [$$ScaleValue]: "space";
@@ -194,9 +198,6 @@ declare namespace EditableTable {
194
198
  size: (value: {
195
199
  readonly [$$PropertyValue]: "width";
196
200
  }) => {
197
- /**
198
- * Change event handler table selection.
199
- */
200
201
  width: {
201
202
  readonly [$$PropertyValue]: "width";
202
203
  };
@@ -273,9 +274,7 @@ declare namespace EditableTable {
273
274
  }) => {
274
275
  marginBottom: {
275
276
  readonly [$$ScaleValue]: "space";
276
- }; /**
277
- * Additional height of the rows.
278
- */
277
+ };
279
278
  };
280
279
  ml: (value: {
281
280
  readonly [$$ScaleValue]: "space";
@@ -307,9 +306,6 @@ declare namespace EditableTable {
307
306
  size: (value: {
308
307
  readonly [$$PropertyValue]: "width";
309
308
  }) => {
310
- /**
311
- * Change event handler table selection.
312
- */
313
309
  width: {
314
310
  readonly [$$PropertyValue]: "width";
315
311
  };
@@ -384,9 +380,7 @@ declare namespace EditableTable {
384
380
  }) => {
385
381
  marginBottom: {
386
382
  readonly [$$ScaleValue]: "space";
387
- }; /**
388
- * Additional height of the rows.
389
- */
383
+ };
390
384
  };
391
385
  ml: (value: {
392
386
  readonly [$$ScaleValue]: "space";
@@ -418,9 +412,6 @@ declare namespace EditableTable {
418
412
  size: (value: {
419
413
  readonly [$$PropertyValue]: "width";
420
414
  }) => {
421
- /**
422
- * Change event handler table selection.
423
- */
424
415
  width: {
425
416
  readonly [$$PropertyValue]: "width";
426
417
  };
@@ -38,6 +38,7 @@ interface MobileTableProps {
38
38
  footerColumnIds?: Set<string>;
39
39
  headerRowSpan?: boolean;
40
40
  keyId?: string;
41
+ sortColumnTitle?: string;
41
42
  }
42
43
  declare const MobileTable: React.ForwardRefExoticComponent<MobileTableProps & React.RefAttributes<HTMLDivElement>>;
43
44
  export default MobileTable;
@@ -1,3 +1,5 @@
1
1
  export * from './Table';
2
+ export type { PaginationLabel, TableLocaleText } from './locale';
3
+ export { defaultTableLocaleText } from './locale';
2
4
  export * from './components';
3
5
  export { default as MobileTable } from './MobileTable';
@@ -0,0 +1,40 @@
1
+ import type { ReactNode } from 'react';
2
+ export interface PaginationLabel {
3
+ showingText?: string;
4
+ showingCountText?: string | ((params: {
5
+ from: number;
6
+ to: number;
7
+ total: number;
8
+ }) => string);
9
+ dialogShowingText?: string;
10
+ previousButton?: string;
11
+ nextButton?: string;
12
+ gotoPageText?: string;
13
+ goToPagePlaceholder?: string;
14
+ btnCancelText?: string;
15
+ btnSubmitText?: string;
16
+ }
17
+ export interface TableLocaleText {
18
+ /** Tooltip (`title` attribute) of a sortable header. */
19
+ sortColumnTitle: string;
20
+ /** Title of the show/hide column dialog on mobile. */
21
+ showColumnTitle: ReactNode;
22
+ emptyDataTitle: ReactNode;
23
+ emptyDataDescription: ReactNode;
24
+ /** Receives the `searchQuery` so each language can place it where its grammar needs it. */
25
+ emptySearchTitle: (params: {
26
+ query: string;
27
+ }) => ReactNode;
28
+ emptySearchDescription: ReactNode;
29
+ pagination: PaginationLabel;
30
+ }
31
+ export declare const defaultTableLocaleText: TableLocaleText;
32
+ export declare const i18nTableLocaleText: (t: any) => TableLocaleText;
33
+ /** Later sources win; an `undefined` value never erases an earlier one. */
34
+ export declare const mergeTableLocaleText: (base: TableLocaleText, ...overrides: (Partial<TableLocaleText> | undefined)[]) => TableLocaleText;
35
+ /**
36
+ * Resolves the table texts. Precedence: the table's own `localeText`, then `MajooProvider`'s
37
+ * `localeText.table`, then the app's `MajooUI/table` translations, then the Indonesian defaults.
38
+ * Several table-level overrides may be passed; later ones win. Pass the same number on every render.
39
+ */
40
+ export declare const useTableLocaleText: (...localeTexts: (Partial<TableLocaleText> | undefined)[]) => TableLocaleText;
@@ -0,0 +1,10 @@
1
+ import * as React from 'react';
2
+ import type { TableLocaleText } from '../../components/table/locale';
3
+ /**
4
+ * Component texts supplied once for the whole app through `MajooProvider`'s `localeText`.
5
+ * Each component reads its own key; any text left unset keeps the component's default.
6
+ */
7
+ export interface MajooLocaleText {
8
+ table?: Partial<TableLocaleText>;
9
+ }
10
+ export declare const LocaleTextContext: React.Context<MajooLocaleText>;