UNPKG

@knowmax/genericlist-fluentuiv9

Version:

Knowmax Generic list with basic CRUD support with Fluent V9 user interface implementation.

1,114 lines (1,110 loc) 46.6 kB
'use strict'; var mobxReactLite = require('mobx-react-lite'); var react = require('@griffel/react'); var tokens = require('@fluentui/tokens'); var jsxRuntime = require('react/jsx-runtime'); var react$1 = require('react'); var reactText = require('@fluentui/react-text'); var genericlistCore = require('@knowmax/genericlist-core'); var reactSpinner = require('@fluentui/react-spinner'); var reactMessageBar = require('@fluentui/react-message-bar'); var reactComponents = require('@fluentui/react-components'); var reactIcons = require('@fluentui/react-icons'); var reactWindow = require('react-window'); var reactVirtualizedAutoSizer = require('react-virtualized-auto-sizer'); var reactButton = require('@fluentui/react-button'); var reactField = require('@fluentui/react-field'); var reactInput = require('@fluentui/react-input'); var reactSwitch = require('@fluentui/react-switch'); var reactCheckbox = require('@fluentui/react-checkbox'); var pagerFluentuiv9 = require('@knowmax/pager-fluentuiv9'); // src/components/list/ListPanel.tsx var useClasses = react.makeStyles({ root: { display: "flex", flexDirection: "column", rowGap: tokens.tokens.spacingVerticalS }, loading: { backgroundColor: tokens.tokens.colorNeutralBackground3 } }); var ListPanel = mobxReactLite.observer(({ loading, children, className }) => { const classes = useClasses(); return /* @__PURE__ */ jsxRuntime.jsx("div", { className: react.mergeClasses(classes.root, loading && classes.loading, className), children }); }); var useClasses2 = react.makeStyles({ root: { padding: tokens.tokens.spacingHorizontalS, boxShadow: tokens.tokens.shadow8 } }); var ListItemPanel = mobxReactLite.observer(({ children, className }) => { const classes = useClasses2(); return /* @__PURE__ */ jsxRuntime.jsx("div", { className: react.mergeClasses(classes.root, className), children }); }); var useClasses3 = react.makeStyles({ root: { display: "flex", justifyContent: "center", alignItems: "center", padding: tokens.tokens.spacingHorizontalL }, spinner: { position: "absolute" } }); var Loader = ({ size }) => { const classes = useClasses3(); return /* @__PURE__ */ jsxRuntime.jsx("div", { className: classes.root, children: /* @__PURE__ */ jsxRuntime.jsx(reactSpinner.Spinner, { className: classes.spinner, size: size === "sm" ? "tiny" : size === "lg" ? "huge" : "medium" }) }); }; var ErrorMessage = ({ error, title }) => { const genericlistsettings = genericlistCore.useGenericListSettings(); const [message, setMessage] = react$1.useState(); react$1.useEffect(() => { if (typeof error === "string") { setMessage(error); } else if (error) { genericlistsettings.onErrorMessage(error).then((m) => setMessage(m)); } }, [error, genericlistsettings]); return /* @__PURE__ */ jsxRuntime.jsx(reactMessageBar.MessageBar, { intent: "error", role: "alert", children: /* @__PURE__ */ jsxRuntime.jsxs(reactMessageBar.MessageBarBody, { children: [ title && /* @__PURE__ */ jsxRuntime.jsx(reactMessageBar.MessageBarTitle, { children: title }), message ] }) }); }; var useClasses4 = reactComponents.makeStyles({ root: { "& .toggle-icon": { transformOrigin: "center", transition: "transform 200ms cubic-bezier(0.4, 0, 0.2, 1)" }, '&[aria-pressed="true"] .toggle-icon': { transform: "rotate(90deg)" }, '&[aria-pressed="false"] .toggle-icon': { transform: "rotate(0deg)" } } }); var ToggleOpenButton = mobxReactLite.observer(({ value = false, disabled, onToggle }) => { const [open, setOpen] = react$1.useState(value); const classes = useClasses4(); react$1.useEffect(() => { setOpen(value); }, [value]); const toggle = react$1.useCallback(() => { if (onToggle) { onToggle(); } setOpen((o) => !o); }, [onToggle]); return /* @__PURE__ */ jsxRuntime.jsx( reactComponents.ToggleButton, { appearance: "transparent", className: classes.root, disabled, checked: open, icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.ChevronRight24Regular, { className: "toggle-icon" }), onClick: toggle } ); }); // src/types/language.ts var GROUP_PLACEHOLDER = "placeholder"; var GROUP_LABEL = "label"; var GROUP_LAYOUT = "layout"; var LANGUAGE_PLACEHOLDERSEARCH = GROUP_PLACEHOLDER + ".search"; var LANGUAGE_LABELNORESULTS = GROUP_LABEL + ".noresults"; var LANGUAGE_LABELRESULTCOUNT = GROUP_LABEL + ".resultcount"; var LANGUAGE_LABELRESET = GROUP_LABEL + ".reset"; var LANGUAGE_LABELRECYCLEBIN = GROUP_LABEL + ".recyclebin"; var LANGUAGE_LAYOUTLIST = GROUP_LAYOUT + ".list"; var LANGUAGE_LAYOUTGRID = GROUP_LAYOUT + ".grid"; var LANGUAGE_LAYOUTCOMPACT = GROUP_LAYOUT + ".compact"; var LANGUAGE_LAYOUTCARD = GROUP_LAYOUT + ".card"; var useClasses5 = react.makeStyles({ listroot: { display: "flex", flexDirection: "column", rowGap: tokens.tokens.spacingVerticalM }, grid: { display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(280px, 1fr))", gap: tokens.tokens.spacingVerticalM }, compact: { rowGap: tokens.tokens.spacingVerticalXS }, card: { display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: tokens.tokens.spacingVerticalM } }); var layoutClassMap = (classes) => ({ grid: classes.grid, compact: classes.compact, card: classes.card }); var List = mobxReactLite.observer(({ list, onRenderListItem, showPager = true, layout = "list", className }) => { const classes = useClasses5(); const settings = genericlistCore.useGenericListSettings(); return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [ list.error && /* @__PURE__ */ jsxRuntime.jsx(ErrorMessage, { error: list.error }), (!list.loaded || list.list.length === 0) && list.loading && /* @__PURE__ */ jsxRuntime.jsx(Loader, {}), list.loaded && !list.loading && list.list.length === 0 && /* @__PURE__ */ jsxRuntime.jsx(reactText.Text, { children: settings.onTranslate(LANGUAGE_LABELNORESULTS) }), /* @__PURE__ */ jsxRuntime.jsxs("div", { className: react.mergeClasses(classes.listroot, className), children: [ list.loaded && /* @__PURE__ */ jsxRuntime.jsx(ListPanel, { loading: list.loading, className: layoutClassMap(classes)[layout], children: list.list.map((item, index) => /* @__PURE__ */ jsxRuntime.jsx(react$1.Fragment, { children: onRenderListItem(item, index) }, index)) }), showPager && /* @__PURE__ */ jsxRuntime.jsx(PagerWrapper, { list }) ] }) ] }); }); var ITEM_HEIGHT_BY_LAYOUT = { list: 90, compact: 64, grid: 90, card: 90 }; var RowRenderer = ({ index, style, ariaAttributes, items, onRenderListItem }) => { const item = items[index]; return /* @__PURE__ */ jsxRuntime.jsx("div", { style, ...ariaAttributes, children: item !== void 0 && onRenderListItem(item, index) }); }; var useClasses6 = react.makeStyles({ root: { display: "flex", flexDirection: "column", rowGap: tokens.tokens.spacingVerticalS }, listContainer: { flex: "1 1 auto", overflow: "hidden" }, loadingFooter: { display: "flex", justifyContent: "center", padding: tokens.tokens.spacingVerticalS } }); var VirtualizedList = mobxReactLite.observer(({ list, onRenderListItem, itemHeight, height, layout = "list", overscanCount = 3, className }) => { const effectiveItemHeight = itemHeight ?? ITEM_HEIGHT_BY_LAYOUT[layout]; const classes = useClasses6(); const settings = genericlistCore.useGenericListSettings(); const [allItems, setAllItems] = react$1.useState([]); const processedPageRef = react$1.useRef(0); const configHash = `${list.filter ?? ""}|${list.orderExpression}|${list.pageSize}`; const isRequestingMoreRef = react$1.useRef(false); react$1.useEffect(() => { list.setPage(1); processedPageRef.current = 0; setAllItems([]); isRequestingMoreRef.current = false; list.load(); }, [list, configHash]); react$1.useEffect(() => { if (!list.loaded || list.loading) return; const incomingPage = list.page; if (incomingPage === 1) { setAllItems(list.list.slice()); processedPageRef.current = 1; } else if (incomingPage > processedPageRef.current) { setAllItems((prev) => [...prev, ...list.list.slice()]); processedPageRef.current = incomingPage; } else { processedPageRef.current = 0; isRequestingMoreRef.current = false; setAllItems([]); list.setPage(1); list.load(); return; } isRequestingMoreRef.current = false; }, [list.loading, list.page, list.loaded]); const loadMore = react$1.useCallback(() => { if (list.loading || isRequestingMoreRef.current || allItems.length >= list.totalCount) return; isRequestingMoreRef.current = true; list.setPage(list.page + 1); list.load(); }, [list, allItems.length]); const handleRowsRendered = react$1.useCallback( (_visibleRows, allRows) => { if (allRows.stopIndex >= allItems.length - 1 - overscanCount) { loadMore(); } }, [allItems.length, overscanCount, loadMore] ); const hasItems = allItems.length > 0; const isInitialLoading = (!list.loaded || allItems.length === 0) && list.loading; const isEmpty = list.loaded && !list.loading && allItems.length === 0; const isLoadingMore = list.loading && hasItems; const rowProps = { items: allItems, onRenderListItem }; return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: react.mergeClasses(classes.root, className), children: [ list.error && /* @__PURE__ */ jsxRuntime.jsx(ErrorMessage, { error: list.error }), isInitialLoading && /* @__PURE__ */ jsxRuntime.jsx(Loader, {}), isEmpty && /* @__PURE__ */ jsxRuntime.jsx(reactText.Text, { children: settings.onTranslate(LANGUAGE_LABELNORESULTS) }), hasItems && /* @__PURE__ */ jsxRuntime.jsx("div", { style: height !== void 0 ? { height } : void 0, className: classes.listContainer, children: height !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx( reactWindow.List, { rowComponent: RowRenderer, rowCount: allItems.length, rowHeight: effectiveItemHeight, rowProps, overscanCount, onRowsRendered: handleRowsRendered, style: { height: "100%", width: "100%" } } ) : /* @__PURE__ */ jsxRuntime.jsx( reactVirtualizedAutoSizer.AutoSizer, { renderProp: ({ height: autoHeight, width }) => /* @__PURE__ */ jsxRuntime.jsx( reactWindow.List, { rowComponent: RowRenderer, rowCount: allItems.length, rowHeight: effectiveItemHeight, rowProps, overscanCount, onRowsRendered: handleRowsRendered, style: { height: autoHeight ?? "100%", width: width ?? "100%" } } ) } ) }), isLoadingMore && /* @__PURE__ */ jsxRuntime.jsx("div", { className: classes.loadingFooter, children: /* @__PURE__ */ jsxRuntime.jsx(Loader, { size: "sm" }) }) ] }); }); var useClasses7 = react.makeStyles({ root: { display: "flex", flexDirection: "column", minWidth: 0, padding: reactComponents.tokens.spacingHorizontalS, backgroundColor: reactComponents.tokens.colorBrandBackground2, boxShadow: reactComponents.tokens.shadow8, position: "sticky", overflowX: "hidden", transitionProperty: "row-gap", transitionDuration: "350ms", transitionTimingFunction: "cubic-bezier(0.4, 0, 0.2, 1)" }, rootOpen: { rowGap: reactComponents.tokens.spacingHorizontalM }, rootClosed: { rowGap: "0px" }, head: { display: "flex", alignItems: "center", justifyContent: "space-between" }, headCollapsible: { cursor: "pointer" }, contents: { display: "flex", flexDirection: "column", rowGap: reactComponents.tokens.spacingHorizontalL, overflow: "hidden", transitionProperty: "max-height, opacity, transform", transitionDuration: "350ms", transitionTimingFunction: "cubic-bezier(0.4, 0, 0.2, 1)" }, contentsOpen: { maxHeight: "2000px", // Large enough to accommodate content opacity: "1", transform: "translateY(0px)" }, contentsClosed: { maxHeight: "0px", opacity: "0", transform: "translateY(-8px)" } }); var SidePanel = mobxReactLite.observer(({ children, caption, showResetFilters = true, showRecycleBinFilter = false, collapsible = false, collapsed = false, list, listId, className, captionClassName }) => { const [open, setOpen] = react$1.useState(!collapsed || !collapsible); const classes = useClasses7(); const toggle = react$1.useCallback(() => { if (collapsible) { setOpen((o) => !o); } }, [collapsible]); return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: react.mergeClasses( classes.root, open ? classes.rootOpen : classes.rootClosed, className ), children: [ /* @__PURE__ */ jsxRuntime.jsxs("section", { className: react.mergeClasses(classes.head, collapsible && classes.headCollapsible), onClick: toggle, "aria-expanded": collapsible ? open : void 0, children: [ caption && /* @__PURE__ */ jsxRuntime.jsx(reactComponents.Caption1Strong, { className: captionClassName, children: caption }), collapsible && /* @__PURE__ */ jsxRuntime.jsx(ToggleOpenButton, { value: open }) ] }), /* @__PURE__ */ jsxRuntime.jsxs("section", { className: react.mergeClasses( classes.contents, open ? classes.contentsOpen : classes.contentsClosed ), children: [ showResetFilters && /* @__PURE__ */ jsxRuntime.jsx(ResetFilters, { list, listId }), showRecycleBinFilter && /* @__PURE__ */ jsxRuntime.jsx(RecycleBinFilter, { listId }), children ] }) ] }); }); var useClasses8 = react.makeStyles({ dropdown: { width: "100%", minWidth: 0 }, dropdownButton: { minWidth: 0, width: "100%" }, withIcon: { display: "flex", alignItems: "center", columnGap: "6px" } }); var OrderSelector = mobxReactLite.observer(({ list, listId }) => { const classes = useClasses8(); const settings = genericlistCore.useGenericListSettings(); const selectedkey = react$1.useMemo(() => { const ordervalue = settings.params.get(genericlistCore.getParamId(genericlistCore.PARAM_ORDER, listId)); if (ordervalue) { const [field, descending] = genericlistCore.parseOrderExpression(ordervalue); const order = list.find((order2) => keyForOrder(order2.field, order2.descending) === keyForOrder(field, descending)); return order ? keyForOrder(order.field, order.descending) : void 0; } else { const order = list.find((order2) => order2.default === true); return order ? keyForOrder(order.field, order.descending) : void 0; } }, [settings.params, list, listId]); const options = react$1.useMemo(() => { return list.filter((order) => !order.isAvailable || order.isAvailable(order, settings.params, listId)).map((order) => ({ key: keyForOrder(order.field, order.descending), text: order.name, data: order })); }, [list, settings.params, listId]); const selectedOrder = react$1.useMemo(() => options.find((o) => o.key === selectedkey)?.data, [options, selectedkey]); const change = react$1.useCallback((_ev, data) => { if (data.optionValue) { const neworder = list.find((order) => keyForOrder(order.field, order.descending) === data.optionValue); const params = new URLSearchParams(settings.params); if (neworder) { params.set(genericlistCore.getParamId(genericlistCore.PARAM_ORDER, listId), `${neworder.field}${neworder.descending ? " desc" : ""}`); } settings.serialize(params); } }, [list, settings.params, listId]); return /* @__PURE__ */ jsxRuntime.jsx( reactComponents.Dropdown, { className: classes.dropdown, value: selectedOrder?.name ?? "", selectedOptions: selectedkey ? [selectedkey] : [], onOptionSelect: change, button: { className: classes.dropdownButton, children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: classes.withIcon, children: [ /* @__PURE__ */ jsxRuntime.jsx(SortIcon, { descending: selectedOrder?.descending, fieldType: selectedOrder?.fieldType }), selectedOrder?.name ] }) }, children: options.map((option) => /* @__PURE__ */ jsxRuntime.jsx(reactComponents.Option, { value: option.key, text: option.text, children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: classes.withIcon, children: [ /* @__PURE__ */ jsxRuntime.jsx(SortIcon, { descending: option.data.descending, fieldType: option.data.fieldType }), option.text ] }) }, option.key)) } ); }); var SortIcon = ({ descending, fieldType }) => { if (fieldType === genericlistCore.FilterValueType.string) { return descending ? /* @__PURE__ */ jsxRuntime.jsx(reactIcons.TextSortDescendingRegular, {}) : /* @__PURE__ */ jsxRuntime.jsx(reactIcons.TextSortAscendingRegular, {}); } return descending ? /* @__PURE__ */ jsxRuntime.jsx(reactIcons.ArrowSortDownRegular, {}) : /* @__PURE__ */ jsxRuntime.jsx(reactIcons.ArrowSortUpRegular, {}); }; var keyForOrder = (field, descending) => `${field}${descending === true}`; var useClasses9 = react.makeStyles({ unicodeIcon: { display: "inline-flex", alignItems: "center", justifyContent: "center", width: "20px", height: "20px", fontSize: "14px", fontWeight: "bold", color: tokens.tokens.colorNeutralForeground1 } }); var UnicodeIcon = ({ symbol, className }) => /* @__PURE__ */ jsxRuntime.jsx("span", { className, "aria-hidden": "true", children: symbol }); var buildOperatorConfigs = (unicodeIconClass) => [ { operator: genericlistCore.FilterOperator.eq, icon: () => /* @__PURE__ */ jsxRuntime.jsx(reactIcons.EqualCircleRegular, {}), ariaLabel: "Equals" }, { operator: genericlistCore.FilterOperator.ne, icon: () => /* @__PURE__ */ jsxRuntime.jsx(reactIcons.EqualOffRegular, {}), ariaLabel: "Not equals" }, { operator: genericlistCore.FilterOperator.gt, icon: () => /* @__PURE__ */ jsxRuntime.jsx(reactIcons.ChevronRightRegular, {}), ariaLabel: "Greater than" }, { operator: genericlistCore.FilterOperator.ge, icon: () => /* @__PURE__ */ jsxRuntime.jsx(UnicodeIcon, { symbol: "\u2265", className: unicodeIconClass }), ariaLabel: "Greater or equal" }, { operator: genericlistCore.FilterOperator.lt, icon: () => /* @__PURE__ */ jsxRuntime.jsx(reactIcons.ChevronLeftRegular, {}), ariaLabel: "Less than" }, { operator: genericlistCore.FilterOperator.le, icon: () => /* @__PURE__ */ jsxRuntime.jsx(UnicodeIcon, { symbol: "\u2264", className: unicodeIconClass }), ariaLabel: "Less or equal" }, { operator: genericlistCore.FilterOperator.contains, icon: () => /* @__PURE__ */ jsxRuntime.jsx(reactIcons.SearchRegular, {}), ariaLabel: "Contains" } ]; var OperatorSelector = mobxReactLite.observer(({ filter, listId }) => { const classes = useClasses9(); const settings = genericlistCore.useGenericListSettings(); const filterparamid = react$1.useMemo(() => genericlistCore.getParamId(filter.id, listId), [filter.id, listId]); const operators = react$1.useMemo(() => filter.operators ?? [genericlistCore.FilterOperator.eq], [filter.operators]); const selected = react$1.useMemo(() => { return settings.params.get(genericlistCore.fieldIdForOperator(filterparamid)) ?? filter.operator; }, [filter.operator, filterparamid, settings.params]); const operatorConfigs = react$1.useMemo(() => buildOperatorConfigs(classes.unicodeIcon), [classes.unicodeIcon]); const getConfig = react$1.useCallback( (op) => operatorConfigs.find((c) => c.operator === op), [operatorConfigs] ); const handleSelect = react$1.useCallback((operator) => { const params = new URLSearchParams(settings.params); if (operator === filter.operator) { params.delete(genericlistCore.fieldIdForOperator(filterparamid)); } else { params.set(genericlistCore.fieldIdForOperator(filterparamid), operator); } settings.serialize(params); }, [filterparamid, filter.operator, settings.params]); const selectedConfig = getConfig(selected); return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: operators.length > 1 && /* @__PURE__ */ jsxRuntime.jsxs(reactComponents.Menu, { children: [ /* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuTrigger, { disableButtonEnhancement: true, children: /* @__PURE__ */ jsxRuntime.jsx( reactComponents.SplitButton, { appearance: "subtle", icon: selectedConfig?.icon(), "aria-label": selectedConfig?.ariaLabel } ) }), /* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuPopover, { children: /* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuList, { children: operators.map((op) => { const config = getConfig(op); if (!config) return null; return /* @__PURE__ */ jsxRuntime.jsx( reactComponents.MenuItem, { icon: config.icon(), "aria-label": config.ariaLabel, onClick: () => handleSelect(op) }, op ); }) }) }) ] }) }); }); var Filter = mobxReactLite.observer(({ filter, listId }) => { const settings = genericlistCore.useGenericListSettings(); const visible = react$1.useMemo(() => { return !filter.isAvailable || filter.isAvailable(filter, settings.params); }, [filter, settings.params]); return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: visible && /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: filter.renderCustom ? /* @__PURE__ */ jsxRuntime.jsx(FilterCustom, { filter, listId }) : filter.valueType === genericlistCore.FilterValueType.boolean ? /* @__PURE__ */ jsxRuntime.jsx(FilterBoolean, { filter, listId }) : filter.options ? /* @__PURE__ */ jsxRuntime.jsx(FilterOptions, { filter, listId }) : /* @__PURE__ */ jsxRuntime.jsx(FilterText, { filter, listId }) }) }); }); var useClasses10 = react.makeStyles({ rootvertical: { display: "flex", flexDirection: "column", rowGap: tokens.tokens.spacingVerticalXS }, buttoncontainer: { display: "flex", flexDirection: "row", alignItems: "end", justifyContent: "end", columnGap: tokens.tokens.spacingHorizontalXS } }); var FilterText = mobxReactLite.observer(({ filter, listId }) => { const classes = useClasses10(); const [value, setValue] = react$1.useState(""); const settings = genericlistCore.useGenericListSettings(); const filterparamid = react$1.useMemo(() => genericlistCore.getParamId(filter.id, listId), [filter.id, listId]); react$1.useEffect(() => { setValue(settings.params.get(filterparamid) ?? ""); }, [settings.params, filterparamid]); const execute = react$1.useCallback((query) => { const params = new URLSearchParams(settings.params); params.delete(filterparamid); if (query !== "") { params.set(filterparamid, query); } else { params.delete(genericlistCore.fieldIdForOperator(filterparamid)); } settings.serialize(params); }, [settings.params, filterparamid]); const changevalue = react$1.useCallback((ev, data) => { setValue(data.value ?? ""); }, []); const clearvalue = react$1.useCallback(() => { setValue(""); execute(""); }, [execute]); const onenter = react$1.useCallback((e) => { if (e.code === "Enter") { execute(value); } }, [execute, value]); const onexecute = react$1.useCallback(() => { execute(value); }, [execute, value]); const allowoperatorselection = react$1.useMemo(() => filter.operators && filter.operators.length > 0, [filter.operators]); return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: classes.rootvertical, children: [ /* @__PURE__ */ jsxRuntime.jsx(reactField.Field, { label: filter.name, children: /* @__PURE__ */ jsxRuntime.jsx( reactInput.Input, { autoComplete: "off", "data-1p-ignore": true, placeholder: filter.placeholderText ?? settings.onTranslate(LANGUAGE_PLACEHOLDERSEARCH), value, spellCheck: false, onChange: changevalue, onKeyUp: onenter } ) }), /* @__PURE__ */ jsxRuntime.jsxs("div", { className: classes.buttoncontainer, children: [ allowoperatorselection && /* @__PURE__ */ jsxRuntime.jsx(OperatorSelector, { filter, listId }), /* @__PURE__ */ jsxRuntime.jsx( reactButton.Button, { onClick: clearvalue, disabled: !value, appearance: "transparent", icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.DismissRegular, {}) } ), /* @__PURE__ */ jsxRuntime.jsx( reactButton.Button, { onClick: onexecute, disabled: !value, appearance: "transparent", icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.SearchRegular, {}) } ) ] }) ] }); }); var FilterCustom = mobxReactLite.observer(({ filter, listId }) => { const settings = genericlistCore.useGenericListSettings(); const filterparamid = react$1.useMemo(() => genericlistCore.getParamId(filter.id, listId), [filter.id, listId]); const selected = react$1.useMemo(() => { return settings.params.get(filterparamid) ?? void 0; }, [filter, settings.params]); const select = react$1.useCallback((value) => { const params = new URLSearchParams(settings.params); params.delete(filterparamid); if (value && value !== "") { params.set(filterparamid, value); } else { params.delete(genericlistCore.fieldIdForOperator(filterparamid)); } settings.serialize(params); }, [filter, settings.params, filterparamid]); return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: filter.renderCustom && /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: filter.renderCustom(filter, selected, select, listId) }) }); }); var useClasses11 = react.makeStyles({ head: { display: "flex", flexDirection: "row", justifyContent: "space-between", alignItems: "center", gap: tokens.tokens.spacingVerticalM, cursor: "pointer", ":hover": { backgroundColor: tokens.tokens.colorSubtleBackgroundHover } }, actions: { display: "flex", flexDirection: "row", alignItems: "center", gap: tokens.tokens.spacingVerticalM } }); var FilterOptions = mobxReactLite.observer(({ filter, listId }) => { const [open, setOpen] = react$1.useState(true); const settings = genericlistCore.useGenericListSettings(); const classes = useClasses11(); const filterparamid = react$1.useMemo(() => genericlistCore.getParamId(filter.id, listId), [filter.id, listId]); react$1.useEffect(() => { if (filter.collapsed === true && !settings.params.get(filterparamid)) { setOpen(false); } }, [filter.collapsed, filterparamid, settings.params]); const toggleopen = react$1.useCallback(() => { setOpen(!open); }, [open]); const selected = react$1.useMemo(() => { const id = settings.params.get(filterparamid); if (id) { return id; } else { return filter.options?.find((o) => o.value === void 0 && o.expression === void 0)?.id; } }, [filter, filterparamid, settings.params]); const select = react$1.useCallback((ev, data) => { const params = new URLSearchParams(settings.params); params.delete(filterparamid); if (data.value) { const o = filter.options?.find((o2) => o2.id === data.value); if (o && (o.expression !== void 0 && o.expression !== "" || o.value !== void 0)) { params.set(filterparamid, o.id); } settings.serialize(params); } }, [filter, filterparamid, settings.params]); const clear = react$1.useCallback((event) => { event.stopPropagation(); const params = new URLSearchParams(settings.params); if (params.has(filterparamid)) { params.delete(filterparamid); settings.serialize(params); } }, [filterparamid, settings.params]); return /* @__PURE__ */ jsxRuntime.jsx(reactField.Field, { label: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: classes.head, onClick: toggleopen, children: [ filter.name, /* @__PURE__ */ jsxRuntime.jsxs("div", { className: classes.actions, children: [ selected !== void 0 && /* @__PURE__ */ jsxRuntime.jsx( reactButton.Button, { onClick: clear, appearance: "transparent", icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.DismissRegular, {}) } ), /* @__PURE__ */ jsxRuntime.jsx(ToggleOpenButton, { value: open }) ] }) ] }), children: open && filter.options && /* @__PURE__ */ jsxRuntime.jsx(reactComponents.RadioGroup, { value: selected ?? "", onChange: select, children: filter.options.map((option) => /* @__PURE__ */ jsxRuntime.jsx(reactComponents.Radio, { value: option.id, label: option.name ?? option.id }, option.id)) }) }); }); var useClasses12 = react.makeStyles({ horizontal: { display: "flex", flexDirection: "row", alignItems: "center" } }); var VALUETRUE = "true"; var VALUEFALSE = "false"; var FilterBoolean = mobxReactLite.observer(({ filter, listId }) => { const classes = useClasses12(); const settings = genericlistCore.useGenericListSettings(); const filterparamid = react$1.useMemo(() => genericlistCore.getParamId(filter.id, listId), [filter.id, listId]); const checked = react$1.useMemo(() => { const value = settings.params.get(filterparamid) ?? void 0; return value === VALUETRUE || value === "1" ? true : value === VALUEFALSE || value === "0" ? false : void 0; }, [filter, settings.params]); const enabled = react$1.useMemo(() => checked !== void 0, [checked]); const toggle = react$1.useCallback((ev, data) => { if (typeof data.checked === "boolean") { const params = new URLSearchParams(settings.params); if (data.checked) { params.delete(filterparamid); params.set(filterparamid, VALUEFALSE); } else if (params.has(filterparamid)) { params.delete(filterparamid); } settings.serialize(params); } }, [settings.params, filterparamid]); const select = react$1.useCallback((ev, data) => { const params = new URLSearchParams(settings.params); params.delete(filterparamid); params.set(filterparamid, data.checked ? VALUETRUE : VALUEFALSE); settings.serialize(params); }, [filter, settings.params, filterparamid]); return /* @__PURE__ */ jsxRuntime.jsx(reactField.Field, { label: filter.name, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: classes.horizontal, children: [ /* @__PURE__ */ jsxRuntime.jsx( reactCheckbox.Checkbox, { checked: enabled, onChange: toggle } ), /* @__PURE__ */ jsxRuntime.jsx( reactSwitch.Switch, { disabled: !enabled, checked: checked === void 0 ? false : checked, onChange: select } ) ] }) }); }); var useClasses13 = react.makeStyles({ root: { display: "flex", flexDirection: "column", rowGap: tokens.tokens.spacingVerticalM } }); var FilterList = mobxReactLite.observer(({ list, listId, className }) => { const classes = useClasses13(); const visiblelist = react$1.useMemo(() => list.filter((filter) => filter.hidden !== true), [list]); return /* @__PURE__ */ jsxRuntime.jsx("div", { className: react.mergeClasses(classes.root, className), children: visiblelist.map((filter) => /* @__PURE__ */ jsxRuntime.jsx(Filter, { filter, listId }, filter.id)) }); }); var useClasses14 = react.makeStyles({ root: { display: "flex", flexDirection: "row", columnGap: tokens.tokens.spacingHorizontalS, boxShadow: tokens.tokens.shadow8, padding: tokens.tokens.spacingHorizontalS, borderRadius: tokens.tokens.borderRadiusMedium, backgroundColor: tokens.tokens.colorBrandBackgroundSelected }, leftright: { display: "flex", flexDirection: "row", justifyContent: "space-between", width: "100%" }, textblock: { display: "flex", flexDirection: "column", overFlowX: "hidden", flexGrow: 1 }, textcolor: { color: tokens.tokens.colorNeutralForegroundStaticInverted } }); var SelectedFilter = mobxReactLite.observer(({ filter, value, allowClear, listId }) => { const classes = useClasses14(); const settings = genericlistCore.useGenericListSettings(); const clear = react$1.useCallback(() => { const params = new URLSearchParams(settings.params); params.delete(genericlistCore.getParamId(filter.id, listId)); settings.serialize(params); }, [settings.params, filter.id, listId]); return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: classes.root, children: [ /* @__PURE__ */ jsxRuntime.jsx(reactIcons.Filter28Filled, { color: tokens.tokens.colorNeutralForegroundStaticInverted, style: { minWidth: "22px" } }), /* @__PURE__ */ jsxRuntime.jsxs("div", { className: classes.leftright, children: [ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: classes.textblock, children: [ /* @__PURE__ */ jsxRuntime.jsx(reactText.Text, { className: classes.textcolor, weight: "bold", children: filter.name }), /* @__PURE__ */ jsxRuntime.jsx(reactText.Text, { className: classes.textcolor, block: true, wrap: true, children: value }) ] }), allowClear && /* @__PURE__ */ jsxRuntime.jsx( reactButton.Button, { appearance: "transparent", icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.DismissRegular, { color: tokens.tokens.colorNeutralForegroundStaticInverted }), onClick: clear } ) ] }) ] }); }); var useClasses15 = react.makeStyles({ list: { display: "flex", flexDirection: "column", rowGap: tokens.tokens.spacingVerticalXS } }); var SelectedFilterList = mobxReactLite.observer(({ list, hiddenOnly = true, allowClear = true, listId, className }) => { const classes = useClasses15(); const settings = genericlistCore.useGenericListSettings(); const infolist = react$1.useMemo(() => { return list.map((filter) => { const value = settings.params.get(genericlistCore.getParamId(filter.id, listId)); return { filter, value: value ?? "" }; }).filter((info) => { return info.value.trim() !== "" && (!hiddenOnly || info.filter.hidden === true); }); }, [list, settings.params, hiddenOnly, listId]); return /* @__PURE__ */ jsxRuntime.jsx("div", { className: react.mergeClasses(classes.list, className), children: infolist.map((info) => /* @__PURE__ */ jsxRuntime.jsx(SelectedFilter, { filter: info.filter, value: info.value, allowClear, listId }, info.filter.id)) }); }); var TotalItems = mobxReactLite.observer(({ list }) => { const settings = genericlistCore.useGenericListSettings(); return /* @__PURE__ */ jsxRuntime.jsx(reactText.Text, { children: settings.onTranslate(LANGUAGE_LABELRESULTCOUNT, { count: list.totalCount }) }); }); var useClasses16 = react.makeStyles({ root: { display: "flex", flexDirection: "row", justifyContent: "space-between", alignItems: "center" } }); var PagerWrapper = mobxReactLite.observer(({ list, className }) => { const classes = useClasses16(); const settings = genericlistCore.useGenericListSettings(); const goto = react$1.useCallback((page) => { const params = new URLSearchParams(settings.params); if (page > 1) { params.set(genericlistCore.getParamId(genericlistCore.PARAM_PAGE, list.id), page.toString()); } else { params.delete(genericlistCore.getParamId(genericlistCore.PARAM_PAGE, list.id)); } settings.serialize(params); }, [settings.params, list.id]); return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: list.loaded && list.totalCount !== 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: react.mergeClasses(classes.root, className), children: [ /* @__PURE__ */ jsxRuntime.jsx( pagerFluentuiv9.Pager, { pageSize: list.pageSize, totalResults: list.totalCount, currentPage: list.page, onChange: goto, display: "buttons" } ), /* @__PURE__ */ jsxRuntime.jsx("div", { children: list.loading ? /* @__PURE__ */ jsxRuntime.jsx(Loader, { size: "sm" }) : /* @__PURE__ */ jsxRuntime.jsx(TotalItems, { list }) }) ] }) }); }); var useClasses17 = react.makeStyles({ button: { width: "100%" } }); var ResetFilters = mobxReactLite.observer(({ list, listId }) => { const classes = useClasses17(); const settings = genericlistCore.useGenericListSettings(); const hasfilter = react$1.useMemo(() => { if (list?.filterList) { const hasActiveFilter = list.filterList.some((filter) => { const paramId = genericlistCore.getParamId(filter.id, listId); return settings.params.has(paramId); }); if (hasActiveFilter) return true; return settings.params.has(genericlistCore.getParamId(genericlistCore.PARAM_ORDER, listId)); } else if (listId !== void 0 && listId !== "") { for (const key of settings.params.keys()) { if (key.startsWith(listId + ".")) { return true; } } return false; } else { return settings.params.toString() !== ""; } }, [settings.params, listId, list?.filterList]); const reset = react$1.useCallback(() => { if (listId !== void 0 && listId !== "") { const params = new URLSearchParams(settings.params); const keysToDelete = Array.from(params.keys()).filter((key) => key.startsWith(listId + ".")); keysToDelete.forEach((key) => params.delete(key)); if (keysToDelete.length > 0) { settings.serialize(params); } } else { if (settings.params.toString() !== "") { settings.serialize(new URLSearchParams()); } } if (list) { const defaultOrder = list.orderList?.find((o) => o.default === true); list.setOrder(defaultOrder); } }, [settings, list]); return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: hasfilter && /* @__PURE__ */ jsxRuntime.jsxs(reactButton.Button, { appearance: "primary", className: classes.button, onClick: reset, children: [ settings.onTranslate(LANGUAGE_LABELRESET), " " ] }) }); }); var RecycleBinFilter = mobxReactLite.observer(({ listId }) => { const settings = genericlistCore.useGenericListSettings(); const paramid = react$1.useMemo(() => genericlistCore.getParamId(genericlistCore.PARAM_DELETED, listId), [listId]); const checked = react$1.useMemo(() => { const value = settings.params.get(paramid); return settings.params.has(paramid) && value !== "false"; }, [paramid, settings.params]); const select = react$1.useCallback((ev, data) => { const params = new URLSearchParams(settings.params); params.delete(paramid); if (data.checked) { params.set(paramid, ""); } settings.serialize(params); }, [settings.params, paramid]); return /* @__PURE__ */ jsxRuntime.jsx( reactSwitch.Switch, { label: settings.onTranslate(LANGUAGE_LABELRECYCLEBIN), checked, onChange: select } ); }); var CreateItem = mobxReactLite.observer((props) => { const { list, template, ...buttonProps } = props; const create = react$1.useCallback(() => { list.create(template); }, [list, template]); return /* @__PURE__ */ jsxRuntime.jsx(reactButton.Button, { ...buttonProps, icon: buttonProps.icon || /* @__PURE__ */ jsxRuntime.jsx(reactIcons.AddRegular, {}), onClick: create }); }); var RefreshList = mobxReactLite.observer((props) => { const { list, ...buttonProps } = props; const refresh = react$1.useCallback(() => { list.setPage(1); list.load(true); }, [list]); return /* @__PURE__ */ jsxRuntime.jsx(reactButton.Button, { ...buttonProps, icon: buttonProps.icon || /* @__PURE__ */ jsxRuntime.jsx(reactIcons.ArrowClockwiseRegular, {}), onClick: refresh }); }); var ALL_LAYOUT_OPTIONS = [ { layout: "list", labelKey: LANGUAGE_LAYOUTLIST, defaultLabel: "List", icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.TextBulletListLtrRegular, {}) }, { layout: "grid", labelKey: LANGUAGE_LAYOUTGRID, defaultLabel: "Grid", icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.GridRegular, {}) }, { layout: "compact", labelKey: LANGUAGE_LAYOUTCOMPACT, defaultLabel: "Compact", icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.TableRegular, {}) }, { layout: "card", labelKey: LANGUAGE_LAYOUTCARD, defaultLabel: "Cards", icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.SquareMultipleRegular, {}) } ]; var useClasses18 = react.makeStyles({ toggleGroup: { display: "inline-flex", flexDirection: "row", border: `1px solid ${tokens.tokens.colorNeutralStroke1}`, borderRadius: tokens.tokens.borderRadiusMedium, overflow: "hidden" }, toggleButton: { borderRadius: "0", border: "none", minWidth: "32px" }, toggleButtonFirst: { borderTopLeftRadius: tokens.tokens.borderRadiusMedium, borderBottomLeftRadius: tokens.tokens.borderRadiusMedium }, toggleButtonLast: { borderTopRightRadius: tokens.tokens.borderRadiusMedium, borderBottomRightRadius: tokens.tokens.borderRadiusMedium } }); var LayoutSelector = mobxReactLite.observer(({ value, onChange, availableLayouts }) => { const classes = useClasses18(); const settings = genericlistCore.useGenericListSettings(); const options = react$1.useMemo(() => { const base = availableLayouts ? ALL_LAYOUT_OPTIONS.filter((o) => availableLayouts.includes(o.layout)) : ALL_LAYOUT_OPTIONS; return base.map((o) => ({ ...o, label: settings.onTranslate(o.labelKey) ?? o.defaultLabel })); }, [availableLayouts, settings.onTranslate]); const handleSelect = react$1.useCallback((layout) => { if (layout !== value) { onChange(layout); } }, [value, onChange]); if (options.length === 0) return null; if (options.length === 2) { return /* @__PURE__ */ jsxRuntime.jsx("div", { className: classes.toggleGroup, role: "toolbar", "aria-label": "Layout", children: options.map((option, i) => /* @__PURE__ */ jsxRuntime.jsx(reactComponents.Tooltip, { content: option.label, relationship: "label", withArrow: true, children: /* @__PURE__ */ jsxRuntime.jsx( reactComponents.ToggleButton, { appearance: "subtle", icon: option.icon, checked: option.layout === value, onClick: () => handleSelect(option.layout), className: react.mergeClasses( classes.toggleButton, i === 0 && classes.toggleButtonFirst, i === options.length - 1 && classes.toggleButtonLast ) } ) }, option.layout)) }); } const current = options.find((o) => o.layout === value) ?? options[0]; return /* @__PURE__ */ jsxRuntime.jsxs(reactComponents.Menu, { children: [ /* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuTrigger, { disableButtonEnhancement: true, children: /* @__PURE__ */ jsxRuntime.jsx(reactComponents.Tooltip, { content: `Layout: ${current.label}`, relationship: "label", withArrow: true, children: /* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuButton, { appearance: "subtle", icon: current.icon, "aria-label": `Layout: ${current.label}` }) }) }), /* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuPopover, { children: /* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuList, { children: options.map((option) => /* @__PURE__ */ jsxRuntime.jsx( reactComponents.MenuItem, { icon: option.icon, onClick: () => handleSelect(option.layout), "aria-pressed": option.layout === value, children: option.label }, option.layout )) }) }) ] }); }); var isCudList = (list) => { return !!list && typeof list.create === "function"; }; var useClasses19 = react.makeStyles({ root: { display: "flex", flexDirection: "row", gap: tokens.tokens.spacingHorizontalL, alignItems: "end" }, far: { marginLeft: "auto", display: "flex", flexDirection: "row", gap: tokens.tokens.spacingHorizontalXS } }); var HeadPanel = mobxReactLite.observer((props) => { const classes = useClasses19(); const canShowRefreshList = !!(props.showRefreshList && props.list); const canShowCreateItem = !!(props.showCreateItem && isCudList(props.list)); const refreshListChildren = props.refreshListProps?.children ?? props.refreshListText; const createItemChildren = props.createItemProps?.children ?? props.createItemText; const showFar = canShowCreateItem || canShowRefreshList || props.showLayoutSelector && props.layout !== void 0 && props.onLayoutChange !== void 0; return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: react.mergeClasses(classes.root, props.className), children: [ props.title && /* @__PURE__ */ jsxRuntime.jsx(reactText.Title3, { children: props.title }), props.children, showFar && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: classes.far, children: [ props.showLayoutSelector && props.layout !== void 0 && props.onLayoutChange && /* @__PURE__ */ jsxRuntime.jsx( LayoutSelector, { value: props.layout, onChange: props.onLayoutChange, availableLayouts: props.availableLayouts } ), canShowRefreshList && props.list && /* @__PURE__ */ jsxRuntime.jsx(RefreshList, { list: props.list, ...props.refreshListProps, children: refreshListChildren }), canShowCreateItem && props.list && /* @__PURE__ */ jsxRuntime.jsx(CreateItem, { list: props.list, ...props.createItemProps, children: createItemChildren }) ] }) ] }); }); exports.ALL_LAYOUT_OPTIONS = ALL_LAYOUT_OPTIONS; exports.CreateItem = CreateItem; exports.Filter = Filter; exports.FilterBoolean = FilterBoolean; exports.FilterCustom = FilterCustom; exports.FilterList = FilterList; exports.FilterOptions = FilterOptions; exports.FilterText = FilterText; exports.HeadPanel = HeadPanel; exports.LayoutSelector = LayoutSelector; exports.List = List; exports.ListItemPanel = ListItemPanel; exports.ListPanel = ListPanel; exports.OperatorSelector = OperatorSelector; exports.OrderSelector = OrderSelector; exports.PagerWrapper = PagerWrapper; exports.RecycleBinFilter = RecycleBinFilter; exports.RefreshList = RefreshList; exports.ResetFilters = ResetFilters; exports.SelectedFilter = SelectedFilter; exports.SelectedFilterList = SelectedFilterList; exports.SidePanel = SidePanel; exports.TotalItems = TotalItems; exports.VirtualizedList = VirtualizedList; //# sourceMappingURL=index.js.map //# sourceMappingURL=index.js.map