mogh_ui 1.1.2 → 1.1.4

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.
@@ -41,11 +41,11 @@ function Config({
41
41
  setUpdate,
42
42
  disabled,
43
43
  onSave,
44
- titleOther,
45
44
  disableSidebar,
46
45
  fileContentsLanguage,
47
46
  enableFancyToml,
48
- groups: _groups
47
+ groups: _groups,
48
+ ...sectionProps
49
49
  }) {
50
50
  const changesMade = Object.keys(update).length ? true : false;
51
51
  const onConfirm = async () => {
@@ -145,7 +145,7 @@ function Config({
145
145
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_core.Group, { visibleFrom: "xs", justify: "flex-end", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SaveOrReset, { unsavedIndicator: true }) }),
146
146
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_core.Stack, { hiddenFrom: "xs", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SaveOrReset, { unsavedIndicator: true, fullWidth: true }) })
147
147
  ] });
148
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_layout.ConfigLayout, { titleOther, SaveOrReset: SaveOrResetComponent, children: [
148
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_layout.ConfigLayout, { SaveOrReset: SaveOrResetComponent, ...sectionProps, children: [
149
149
  disableSidebar && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
150
150
  GroupsComponent,
151
151
  SaveOrResetComponent
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/config/index.tsx"],"sourcesContent":["import { Fragment, ReactNode, SetStateAction, useMemo } from \"react\";\nimport { MonacoLanguage } from \"../monaco\";\nimport {\n Anchor,\n Box,\n Button,\n Flex,\n Group,\n ScrollArea,\n Select,\n Stack,\n Text,\n} from \"@mantine/core\";\nimport { ConfirmUpdate } from \"./confirm\";\nimport { Bookmark, History } from \"lucide-react\";\nimport { ConfigGroup } from \"./group\";\nimport { UnsavedChanges } from \"./unsaved-changes\";\nimport { ConfigLayout } from \"./layout\";\n\nexport * from \"./confirm\";\nexport * from \"./group\";\nexport * from \"./item\";\nexport * from \"./layout\";\nexport * from \"./unsaved-changes\";\n\nexport interface ConfigFieldArgs {\n label?: string;\n description?: ReactNode;\n /** Use a selector instead of input */\n options?: { value: string; label?: string; icon?: ReactNode }[];\n placeholder?: string;\n hidden?: boolean;\n disabled?: boolean;\n}\n\nexport interface ConfigGroupArgs<T> {\n label: string;\n labelExtra?: ReactNode;\n icon?: ReactNode;\n description?: ReactNode;\n actions?: ReactNode;\n hidden?: boolean;\n labelHidden?: boolean;\n contentHidden?: boolean;\n fields: {\n [K in keyof Partial<T>]:\n | boolean\n | ConfigFieldArgs\n | ((value: T[K], set: (value: Partial<T>) => void) => ReactNode);\n };\n}\n\nexport interface ConfigProps<T> {\n original: T;\n update: Partial<T>;\n setUpdate: React.Dispatch<SetStateAction<Partial<T>>>;\n disabled: boolean;\n onSave: () => Promise<unknown>;\n titleOther?: ReactNode;\n disableSidebar?: boolean;\n fileContentsLanguage?: MonacoLanguage;\n enableFancyToml?: boolean;\n groups: Record<\n string, // Section key\n ConfigGroupArgs<T>[] | false | undefined\n >;\n}\n\nexport function Config<T>({\n original,\n update,\n setUpdate,\n disabled,\n onSave,\n titleOther,\n disableSidebar,\n fileContentsLanguage,\n enableFancyToml,\n groups: _groups,\n}: ConfigProps<T>) {\n const changesMade = Object.keys(update).length ? true : false;\n const onConfirm = async () => {\n await onSave();\n setUpdate({});\n };\n const onReset = () => setUpdate({});\n\n const groups = useMemo(\n () => Object.entries(_groups).filter(([_, groupArgs]) => !!groupArgs),\n [_groups],\n );\n\n const GroupsComponent = useMemo(\n () =>\n groups.map(([group, groupArgs]) => {\n return (\n <Fragment key={group}>\n {group && (\n <Text visibleFrom=\"lg\" fz=\"h2\" tt=\"uppercase\" mt=\"xl\">\n {group}\n </Text>\n )}\n\n <Stack>\n {(groupArgs as ConfigGroupArgs<T>[])\n .filter(({ hidden }) => !hidden)\n .map(\n ({\n label,\n labelHidden,\n icon,\n labelExtra,\n actions,\n description,\n contentHidden,\n fields,\n }) => (\n <Stack\n key={group + label}\n id={group + label}\n p=\"xl\"\n gap=\"md\"\n className=\"bordered-light\"\n bdrs=\"md\"\n style={{ scrollMarginTop: 94 }}\n >\n {!labelHidden && (\n <Group justify=\"space-between\">\n <Stack gap=\"0\">\n <Group>\n {icon}\n <Text fz=\"h3\">{label}</Text>\n {labelExtra}\n </Group>\n {description && (\n <Text c=\"dimmed\">{description}</Text>\n )}\n </Stack>\n {actions}\n </Group>\n )}\n {!contentHidden && (\n <ConfigGroup\n config={original}\n update={update}\n setUpdate={(u) => setUpdate((p) => ({ ...p, ...u }))}\n fields={fields}\n disabled={disabled}\n />\n )}\n </Stack>\n ),\n )}\n </Stack>\n </Fragment>\n );\n }),\n [groups],\n );\n\n const SaveOrReset = ({\n unsavedIndicator,\n fullWidth,\n }: {\n unsavedIndicator?: boolean;\n fullWidth?: boolean;\n }) =>\n changesMade && (\n <>\n {unsavedIndicator && <UnsavedChanges fullWidth={fullWidth} />}\n <Button\n variant=\"outline\"\n onClick={onReset}\n disabled={disabled || !changesMade}\n leftSection={<History size=\"1rem\" />}\n fullWidth={fullWidth}\n w={fullWidth ? undefined : 100}\n >\n Reset\n </Button>\n <ConfirmUpdate\n original={original}\n update={update}\n onConfirm={onConfirm}\n disabled={disabled}\n fileContentsLanguage={fileContentsLanguage}\n fullWidth={fullWidth}\n enableFancyToml={enableFancyToml}\n />\n </>\n );\n\n const SaveOrResetComponent = changesMade && (\n <>\n <Group visibleFrom=\"xs\" justify=\"flex-end\">\n <SaveOrReset unsavedIndicator />\n </Group>\n <Stack hiddenFrom=\"xs\">\n <SaveOrReset unsavedIndicator fullWidth />\n </Stack>\n </>\n );\n\n return (\n <ConfigLayout titleOther={titleOther} SaveOrReset={SaveOrResetComponent}>\n {disableSidebar && (\n <>\n {GroupsComponent}\n {SaveOrResetComponent}\n </>\n )}\n {!disableSidebar && (\n <Flex w=\"100%\" gap=\"md\" direction={{ base: \"column\", lg: \"row\" }}>\n {/** SIDEBAR (LG) */}\n <Box\n visibleFrom=\"lg\"\n pos=\"relative\"\n className=\"bordered-light\"\n style={{\n borderLeftWidth: 0,\n borderBottomWidth: 0,\n borderTopRightRadius: \"var(--mantine-radius-md)\",\n }}\n >\n <Stack pos=\"sticky\" w={175} top={88} pb={24} m=\"lg\">\n {/** ANCHORS */}\n <ScrollArea\n mah={\n changesMade ? \"calc(100vh - 220px)\" : \"calc(100vh - 130px)\"\n }\n >\n <Stack>\n {groups\n .filter(([_, groupArgs]) => groupArgs)\n .map(([group, groupArgs]) => (\n <Stack key={group} gap=\"xs\">\n <Group justify=\"flex-end\" mr=\"md\" c=\"dimmed\">\n <Bookmark size=\"1rem\" />\n <Text tt=\"uppercase\">{group || \"GENERAL\"}</Text>\n </Group>\n <Stack gap=\"0.1rem\">\n {groupArgs &&\n groupArgs\n .filter((groupArgs) => !groupArgs.hidden)\n .map((groupArgs) => (\n <Button\n key={group + groupArgs.label}\n variant=\"subtle\"\n justify=\"flex-end\"\n size=\"sm\"\n fullWidth\n renderRoot={(props) => (\n <Anchor\n href={\"#\" + group + groupArgs.label}\n {...props}\n />\n )}\n >\n {groupArgs.label}\n </Button>\n ))}\n </Stack>\n </Stack>\n ))}\n </Stack>\n </ScrollArea>\n\n {/** SAVE */}\n <Stack gap=\"xs\">\n <SaveOrReset fullWidth />\n </Stack>\n </Stack>\n </Box>\n\n {/** SELECTOR (MOBILE) */}\n <Select\n hiddenFrom=\"lg\"\n className=\"select-nondimmed-placeholder\"\n placeholder=\"Go To\"\n leftSection={<Bookmark size=\"1rem\" />}\n value={null}\n data={groups\n .filter(([_, groupArgs]) => groupArgs)\n .map(([group, groupArgs]) => ({\n group,\n items: (groupArgs as ConfigGroupArgs<T>[]).map((arg) => ({\n label: arg.label,\n value: group + arg.label,\n })),\n }))}\n onChange={(group) => {\n if (!group) return;\n window.location.hash = group;\n }}\n />\n\n {/** CONTENT */}\n <Stack style={{ flexGrow: 1 }} gap=\"md\">\n {GroupsComponent}\n {SaveOrResetComponent}\n </Stack>\n </Flex>\n )}\n </ConfigLayout>\n );\n}\n"],"mappings":"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","names":["groupArgs"]}
1
+ {"version":3,"sources":["../../../src/components/config/index.tsx"],"sourcesContent":["import { Fragment, ReactNode, SetStateAction, useMemo } from \"react\";\nimport { MonacoLanguage } from \"../monaco\";\nimport {\n Anchor,\n Box,\n Button,\n Flex,\n Group,\n ScrollArea,\n Select,\n Stack,\n Text,\n} from \"@mantine/core\";\nimport { ConfirmUpdate } from \"./confirm\";\nimport { Bookmark, History } from \"lucide-react\";\nimport { ConfigGroup } from \"./group\";\nimport { UnsavedChanges } from \"./unsaved-changes\";\nimport { ConfigLayout } from \"./layout\";\nimport { SectionProps } from \"../section\";\n\nexport * from \"./confirm\";\nexport * from \"./group\";\nexport * from \"./item\";\nexport * from \"./layout\";\nexport * from \"./unsaved-changes\";\n\nexport interface ConfigFieldArgs {\n label?: string;\n description?: ReactNode;\n /** Use a selector instead of input */\n options?: { value: string; label?: string; icon?: ReactNode }[];\n placeholder?: string;\n hidden?: boolean;\n disabled?: boolean;\n}\n\nexport interface ConfigGroupArgs<T> {\n label: string;\n labelExtra?: ReactNode;\n icon?: ReactNode;\n description?: ReactNode;\n actions?: ReactNode;\n hidden?: boolean;\n labelHidden?: boolean;\n contentHidden?: boolean;\n fields: {\n [K in keyof Partial<T>]:\n | boolean\n | ConfigFieldArgs\n | ((value: T[K], set: (value: Partial<T>) => void) => ReactNode);\n };\n}\n\nexport interface ConfigProps<T> extends SectionProps {\n original: T;\n update: Partial<T>;\n setUpdate: React.Dispatch<SetStateAction<Partial<T>>>;\n disabled: boolean;\n onSave: () => Promise<unknown>;\n disableSidebar?: boolean;\n fileContentsLanguage?: MonacoLanguage;\n enableFancyToml?: boolean;\n groups: Record<\n string, // Section key\n ConfigGroupArgs<T>[] | false | undefined\n >;\n}\n\nexport function Config<T>({\n original,\n update,\n setUpdate,\n disabled,\n onSave,\n disableSidebar,\n fileContentsLanguage,\n enableFancyToml,\n groups: _groups,\n ...sectionProps\n}: ConfigProps<T>) {\n const changesMade = Object.keys(update).length ? true : false;\n const onConfirm = async () => {\n await onSave();\n setUpdate({});\n };\n const onReset = () => setUpdate({});\n\n const groups = useMemo(\n () => Object.entries(_groups).filter(([_, groupArgs]) => !!groupArgs),\n [_groups],\n );\n\n const GroupsComponent = useMemo(\n () =>\n groups.map(([group, groupArgs]) => {\n return (\n <Fragment key={group}>\n {group && (\n <Text visibleFrom=\"lg\" fz=\"h2\" tt=\"uppercase\" mt=\"xl\">\n {group}\n </Text>\n )}\n\n <Stack>\n {(groupArgs as ConfigGroupArgs<T>[])\n .filter(({ hidden }) => !hidden)\n .map(\n ({\n label,\n labelHidden,\n icon,\n labelExtra,\n actions,\n description,\n contentHidden,\n fields,\n }) => (\n <Stack\n key={group + label}\n id={group + label}\n p=\"xl\"\n gap=\"md\"\n className=\"bordered-light\"\n bdrs=\"md\"\n style={{ scrollMarginTop: 94 }}\n >\n {!labelHidden && (\n <Group justify=\"space-between\">\n <Stack gap=\"0\">\n <Group>\n {icon}\n <Text fz=\"h3\">{label}</Text>\n {labelExtra}\n </Group>\n {description && (\n <Text c=\"dimmed\">{description}</Text>\n )}\n </Stack>\n {actions}\n </Group>\n )}\n {!contentHidden && (\n <ConfigGroup\n config={original}\n update={update}\n setUpdate={(u) => setUpdate((p) => ({ ...p, ...u }))}\n fields={fields}\n disabled={disabled}\n />\n )}\n </Stack>\n ),\n )}\n </Stack>\n </Fragment>\n );\n }),\n [groups],\n );\n\n const SaveOrReset = ({\n unsavedIndicator,\n fullWidth,\n }: {\n unsavedIndicator?: boolean;\n fullWidth?: boolean;\n }) =>\n changesMade && (\n <>\n {unsavedIndicator && <UnsavedChanges fullWidth={fullWidth} />}\n <Button\n variant=\"outline\"\n onClick={onReset}\n disabled={disabled || !changesMade}\n leftSection={<History size=\"1rem\" />}\n fullWidth={fullWidth}\n w={fullWidth ? undefined : 100}\n >\n Reset\n </Button>\n <ConfirmUpdate\n original={original}\n update={update}\n onConfirm={onConfirm}\n disabled={disabled}\n fileContentsLanguage={fileContentsLanguage}\n fullWidth={fullWidth}\n enableFancyToml={enableFancyToml}\n />\n </>\n );\n\n const SaveOrResetComponent = changesMade && (\n <>\n <Group visibleFrom=\"xs\" justify=\"flex-end\">\n <SaveOrReset unsavedIndicator />\n </Group>\n <Stack hiddenFrom=\"xs\">\n <SaveOrReset unsavedIndicator fullWidth />\n </Stack>\n </>\n );\n\n return (\n <ConfigLayout SaveOrReset={SaveOrResetComponent} {...sectionProps}>\n {disableSidebar && (\n <>\n {GroupsComponent}\n {SaveOrResetComponent}\n </>\n )}\n {!disableSidebar && (\n <Flex w=\"100%\" gap=\"md\" direction={{ base: \"column\", lg: \"row\" }}>\n {/** SIDEBAR (LG) */}\n <Box\n visibleFrom=\"lg\"\n pos=\"relative\"\n className=\"bordered-light\"\n style={{\n borderLeftWidth: 0,\n borderBottomWidth: 0,\n borderTopRightRadius: \"var(--mantine-radius-md)\",\n }}\n >\n <Stack pos=\"sticky\" w={175} top={88} pb={24} m=\"lg\">\n {/** ANCHORS */}\n <ScrollArea\n mah={\n changesMade ? \"calc(100vh - 220px)\" : \"calc(100vh - 130px)\"\n }\n >\n <Stack>\n {groups\n .filter(([_, groupArgs]) => groupArgs)\n .map(([group, groupArgs]) => (\n <Stack key={group} gap=\"xs\">\n <Group justify=\"flex-end\" mr=\"md\" c=\"dimmed\">\n <Bookmark size=\"1rem\" />\n <Text tt=\"uppercase\">{group || \"GENERAL\"}</Text>\n </Group>\n <Stack gap=\"0.1rem\">\n {groupArgs &&\n groupArgs\n .filter((groupArgs) => !groupArgs.hidden)\n .map((groupArgs) => (\n <Button\n key={group + groupArgs.label}\n variant=\"subtle\"\n justify=\"flex-end\"\n size=\"sm\"\n fullWidth\n renderRoot={(props) => (\n <Anchor\n href={\"#\" + group + groupArgs.label}\n {...props}\n />\n )}\n >\n {groupArgs.label}\n </Button>\n ))}\n </Stack>\n </Stack>\n ))}\n </Stack>\n </ScrollArea>\n\n {/** SAVE */}\n <Stack gap=\"xs\">\n <SaveOrReset fullWidth />\n </Stack>\n </Stack>\n </Box>\n\n {/** SELECTOR (MOBILE) */}\n <Select\n hiddenFrom=\"lg\"\n className=\"select-nondimmed-placeholder\"\n placeholder=\"Go To\"\n leftSection={<Bookmark size=\"1rem\" />}\n value={null}\n data={groups\n .filter(([_, groupArgs]) => groupArgs)\n .map(([group, groupArgs]) => ({\n group,\n items: (groupArgs as ConfigGroupArgs<T>[]).map((arg) => ({\n label: arg.label,\n value: group + arg.label,\n })),\n }))}\n onChange={(group) => {\n if (!group) return;\n window.location.hash = group;\n }}\n />\n\n {/** CONTENT */}\n <Stack style={{ flexGrow: 1 }} gap=\"md\">\n {GroupsComponent}\n {SaveOrResetComponent}\n </Stack>\n </Flex>\n )}\n </ConfigLayout>\n );\n}\n"],"mappings":"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","names":["groupArgs"]}
@@ -1,5 +1,6 @@
1
1
  import { ReactNode, SetStateAction } from "react";
2
2
  import { MonacoLanguage } from "../monaco";
3
+ import { SectionProps } from "../section";
3
4
  export * from "./confirm";
4
5
  export * from "./group";
5
6
  export * from "./item";
@@ -31,13 +32,12 @@ export interface ConfigGroupArgs<T> {
31
32
  [K in keyof Partial<T>]: boolean | ConfigFieldArgs | ((value: T[K], set: (value: Partial<T>) => void) => ReactNode);
32
33
  };
33
34
  }
34
- export interface ConfigProps<T> {
35
+ export interface ConfigProps<T> extends SectionProps {
35
36
  original: T;
36
37
  update: Partial<T>;
37
38
  setUpdate: React.Dispatch<SetStateAction<Partial<T>>>;
38
39
  disabled: boolean;
39
40
  onSave: () => Promise<unknown>;
40
- titleOther?: ReactNode;
41
41
  disableSidebar?: boolean;
42
42
  fileContentsLanguage?: MonacoLanguage;
43
43
  enableFancyToml?: boolean;
@@ -45,5 +45,5 @@ export interface ConfigProps<T> {
45
45
  // Section key
46
46
  ConfigGroupArgs<T>[] | false | undefined>;
47
47
  }
48
- export declare function Config<T>({ original, update, setUpdate, disabled, onSave, titleOther, disableSidebar, fileContentsLanguage, enableFancyToml, groups: _groups, }: ConfigProps<T>): import("react").JSX.Element;
48
+ export declare function Config<T>({ original, update, setUpdate, disabled, onSave, disableSidebar, fileContentsLanguage, enableFancyToml, groups: _groups, ...sectionProps }: ConfigProps<T>): import("react").JSX.Element;
49
49
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/config/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,SAAS,EAAE,cAAc,EAAW,MAAM,OAAO,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAkB3C,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,mBAAmB,CAAC;AAElC,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,sCAAsC;IACtC,OAAO,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,SAAS,CAAA;KAAE,EAAE,CAAC;IAChE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,eAAe,CAAC,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,MAAM,EAAE;SACL,CAAC,IAAI,MAAM,OAAO,CAAC,CAAC,CAAC,GAClB,OAAO,GACP,eAAe,GACf,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,IAAI,KAAK,SAAS,CAAC;KACnE,CAAC;CACH;AAED,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,QAAQ,EAAE,CAAC,CAAC;IACZ,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IACnB,SAAS,EAAE,KAAK,CAAC,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACtD,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/B,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,oBAAoB,CAAC,EAAE,cAAc,CAAC;IACtC,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,MAAM,EAAE,MAAM,CACZ,MAAM,EAAE,cAAc;IACtB,AADQ,cAAc;IACtB,eAAe,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,GAAG,SAAS,CACzC,CAAC;CACH;AAED,wBAAgB,MAAM,CAAC,CAAC,EAAE,EACxB,QAAQ,EACR,MAAM,EACN,SAAS,EACT,QAAQ,EACR,MAAM,EACN,UAAU,EACV,cAAc,EACd,oBAAoB,EACpB,eAAe,EACf,MAAM,EAAE,OAAO,GAChB,EAAE,WAAW,CAAC,CAAC,CAAC,+BAkOhB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/config/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,SAAS,EAAE,cAAc,EAAW,MAAM,OAAO,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAiB3C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,mBAAmB,CAAC;AAElC,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,sCAAsC;IACtC,OAAO,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,SAAS,CAAA;KAAE,EAAE,CAAC;IAChE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,eAAe,CAAC,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,MAAM,EAAE;SACL,CAAC,IAAI,MAAM,OAAO,CAAC,CAAC,CAAC,GAClB,OAAO,GACP,eAAe,GACf,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,IAAI,KAAK,SAAS,CAAC;KACnE,CAAC;CACH;AAED,MAAM,WAAW,WAAW,CAAC,CAAC,CAAE,SAAQ,YAAY;IAClD,QAAQ,EAAE,CAAC,CAAC;IACZ,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IACnB,SAAS,EAAE,KAAK,CAAC,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACtD,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,oBAAoB,CAAC,EAAE,cAAc,CAAC;IACtC,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,MAAM,EAAE,MAAM,CACZ,MAAM,EAAE,cAAc;IACtB,AADQ,cAAc;IACtB,eAAe,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,GAAG,SAAS,CACzC,CAAC;CACH;AAED,wBAAgB,MAAM,CAAC,CAAC,EAAE,EACxB,QAAQ,EACR,MAAM,EACN,SAAS,EACT,QAAQ,EACR,MAAM,EACN,cAAc,EACd,oBAAoB,EACpB,eAAe,EACf,MAAM,EAAE,OAAO,EACf,GAAG,YAAY,EAChB,EAAE,WAAW,CAAC,CAAC,CAAC,+BAkOhB"}
@@ -27,11 +27,11 @@ function Config({
27
27
  setUpdate,
28
28
  disabled,
29
29
  onSave,
30
- titleOther,
31
30
  disableSidebar,
32
31
  fileContentsLanguage,
33
32
  enableFancyToml,
34
- groups: _groups
33
+ groups: _groups,
34
+ ...sectionProps
35
35
  }) {
36
36
  const changesMade = Object.keys(update).length ? true : false;
37
37
  const onConfirm = async () => {
@@ -131,7 +131,7 @@ function Config({
131
131
  /* @__PURE__ */ jsx(Group, { visibleFrom: "xs", justify: "flex-end", children: /* @__PURE__ */ jsx(SaveOrReset, { unsavedIndicator: true }) }),
132
132
  /* @__PURE__ */ jsx(Stack, { hiddenFrom: "xs", children: /* @__PURE__ */ jsx(SaveOrReset, { unsavedIndicator: true, fullWidth: true }) })
133
133
  ] });
134
- return /* @__PURE__ */ jsxs(ConfigLayout, { titleOther, SaveOrReset: SaveOrResetComponent, children: [
134
+ return /* @__PURE__ */ jsxs(ConfigLayout, { SaveOrReset: SaveOrResetComponent, ...sectionProps, children: [
135
135
  disableSidebar && /* @__PURE__ */ jsxs(Fragment, { children: [
136
136
  GroupsComponent,
137
137
  SaveOrResetComponent
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/config/index.tsx"],"sourcesContent":["import { Fragment, ReactNode, SetStateAction, useMemo } from \"react\";\nimport { MonacoLanguage } from \"../monaco\";\nimport {\n Anchor,\n Box,\n Button,\n Flex,\n Group,\n ScrollArea,\n Select,\n Stack,\n Text,\n} from \"@mantine/core\";\nimport { ConfirmUpdate } from \"./confirm\";\nimport { Bookmark, History } from \"lucide-react\";\nimport { ConfigGroup } from \"./group\";\nimport { UnsavedChanges } from \"./unsaved-changes\";\nimport { ConfigLayout } from \"./layout\";\n\nexport * from \"./confirm\";\nexport * from \"./group\";\nexport * from \"./item\";\nexport * from \"./layout\";\nexport * from \"./unsaved-changes\";\n\nexport interface ConfigFieldArgs {\n label?: string;\n description?: ReactNode;\n /** Use a selector instead of input */\n options?: { value: string; label?: string; icon?: ReactNode }[];\n placeholder?: string;\n hidden?: boolean;\n disabled?: boolean;\n}\n\nexport interface ConfigGroupArgs<T> {\n label: string;\n labelExtra?: ReactNode;\n icon?: ReactNode;\n description?: ReactNode;\n actions?: ReactNode;\n hidden?: boolean;\n labelHidden?: boolean;\n contentHidden?: boolean;\n fields: {\n [K in keyof Partial<T>]:\n | boolean\n | ConfigFieldArgs\n | ((value: T[K], set: (value: Partial<T>) => void) => ReactNode);\n };\n}\n\nexport interface ConfigProps<T> {\n original: T;\n update: Partial<T>;\n setUpdate: React.Dispatch<SetStateAction<Partial<T>>>;\n disabled: boolean;\n onSave: () => Promise<unknown>;\n titleOther?: ReactNode;\n disableSidebar?: boolean;\n fileContentsLanguage?: MonacoLanguage;\n enableFancyToml?: boolean;\n groups: Record<\n string, // Section key\n ConfigGroupArgs<T>[] | false | undefined\n >;\n}\n\nexport function Config<T>({\n original,\n update,\n setUpdate,\n disabled,\n onSave,\n titleOther,\n disableSidebar,\n fileContentsLanguage,\n enableFancyToml,\n groups: _groups,\n}: ConfigProps<T>) {\n const changesMade = Object.keys(update).length ? true : false;\n const onConfirm = async () => {\n await onSave();\n setUpdate({});\n };\n const onReset = () => setUpdate({});\n\n const groups = useMemo(\n () => Object.entries(_groups).filter(([_, groupArgs]) => !!groupArgs),\n [_groups],\n );\n\n const GroupsComponent = useMemo(\n () =>\n groups.map(([group, groupArgs]) => {\n return (\n <Fragment key={group}>\n {group && (\n <Text visibleFrom=\"lg\" fz=\"h2\" tt=\"uppercase\" mt=\"xl\">\n {group}\n </Text>\n )}\n\n <Stack>\n {(groupArgs as ConfigGroupArgs<T>[])\n .filter(({ hidden }) => !hidden)\n .map(\n ({\n label,\n labelHidden,\n icon,\n labelExtra,\n actions,\n description,\n contentHidden,\n fields,\n }) => (\n <Stack\n key={group + label}\n id={group + label}\n p=\"xl\"\n gap=\"md\"\n className=\"bordered-light\"\n bdrs=\"md\"\n style={{ scrollMarginTop: 94 }}\n >\n {!labelHidden && (\n <Group justify=\"space-between\">\n <Stack gap=\"0\">\n <Group>\n {icon}\n <Text fz=\"h3\">{label}</Text>\n {labelExtra}\n </Group>\n {description && (\n <Text c=\"dimmed\">{description}</Text>\n )}\n </Stack>\n {actions}\n </Group>\n )}\n {!contentHidden && (\n <ConfigGroup\n config={original}\n update={update}\n setUpdate={(u) => setUpdate((p) => ({ ...p, ...u }))}\n fields={fields}\n disabled={disabled}\n />\n )}\n </Stack>\n ),\n )}\n </Stack>\n </Fragment>\n );\n }),\n [groups],\n );\n\n const SaveOrReset = ({\n unsavedIndicator,\n fullWidth,\n }: {\n unsavedIndicator?: boolean;\n fullWidth?: boolean;\n }) =>\n changesMade && (\n <>\n {unsavedIndicator && <UnsavedChanges fullWidth={fullWidth} />}\n <Button\n variant=\"outline\"\n onClick={onReset}\n disabled={disabled || !changesMade}\n leftSection={<History size=\"1rem\" />}\n fullWidth={fullWidth}\n w={fullWidth ? undefined : 100}\n >\n Reset\n </Button>\n <ConfirmUpdate\n original={original}\n update={update}\n onConfirm={onConfirm}\n disabled={disabled}\n fileContentsLanguage={fileContentsLanguage}\n fullWidth={fullWidth}\n enableFancyToml={enableFancyToml}\n />\n </>\n );\n\n const SaveOrResetComponent = changesMade && (\n <>\n <Group visibleFrom=\"xs\" justify=\"flex-end\">\n <SaveOrReset unsavedIndicator />\n </Group>\n <Stack hiddenFrom=\"xs\">\n <SaveOrReset unsavedIndicator fullWidth />\n </Stack>\n </>\n );\n\n return (\n <ConfigLayout titleOther={titleOther} SaveOrReset={SaveOrResetComponent}>\n {disableSidebar && (\n <>\n {GroupsComponent}\n {SaveOrResetComponent}\n </>\n )}\n {!disableSidebar && (\n <Flex w=\"100%\" gap=\"md\" direction={{ base: \"column\", lg: \"row\" }}>\n {/** SIDEBAR (LG) */}\n <Box\n visibleFrom=\"lg\"\n pos=\"relative\"\n className=\"bordered-light\"\n style={{\n borderLeftWidth: 0,\n borderBottomWidth: 0,\n borderTopRightRadius: \"var(--mantine-radius-md)\",\n }}\n >\n <Stack pos=\"sticky\" w={175} top={88} pb={24} m=\"lg\">\n {/** ANCHORS */}\n <ScrollArea\n mah={\n changesMade ? \"calc(100vh - 220px)\" : \"calc(100vh - 130px)\"\n }\n >\n <Stack>\n {groups\n .filter(([_, groupArgs]) => groupArgs)\n .map(([group, groupArgs]) => (\n <Stack key={group} gap=\"xs\">\n <Group justify=\"flex-end\" mr=\"md\" c=\"dimmed\">\n <Bookmark size=\"1rem\" />\n <Text tt=\"uppercase\">{group || \"GENERAL\"}</Text>\n </Group>\n <Stack gap=\"0.1rem\">\n {groupArgs &&\n groupArgs\n .filter((groupArgs) => !groupArgs.hidden)\n .map((groupArgs) => (\n <Button\n key={group + groupArgs.label}\n variant=\"subtle\"\n justify=\"flex-end\"\n size=\"sm\"\n fullWidth\n renderRoot={(props) => (\n <Anchor\n href={\"#\" + group + groupArgs.label}\n {...props}\n />\n )}\n >\n {groupArgs.label}\n </Button>\n ))}\n </Stack>\n </Stack>\n ))}\n </Stack>\n </ScrollArea>\n\n {/** SAVE */}\n <Stack gap=\"xs\">\n <SaveOrReset fullWidth />\n </Stack>\n </Stack>\n </Box>\n\n {/** SELECTOR (MOBILE) */}\n <Select\n hiddenFrom=\"lg\"\n className=\"select-nondimmed-placeholder\"\n placeholder=\"Go To\"\n leftSection={<Bookmark size=\"1rem\" />}\n value={null}\n data={groups\n .filter(([_, groupArgs]) => groupArgs)\n .map(([group, groupArgs]) => ({\n group,\n items: (groupArgs as ConfigGroupArgs<T>[]).map((arg) => ({\n label: arg.label,\n value: group + arg.label,\n })),\n }))}\n onChange={(group) => {\n if (!group) return;\n window.location.hash = group;\n }}\n />\n\n {/** CONTENT */}\n <Stack style={{ flexGrow: 1 }} gap=\"md\">\n {GroupsComponent}\n {SaveOrResetComponent}\n </Stack>\n </Flex>\n )}\n </ConfigLayout>\n );\n}\n"],"mappings":"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","names":["Fragment","groupArgs"]}
1
+ {"version":3,"sources":["../../../src/components/config/index.tsx"],"sourcesContent":["import { Fragment, ReactNode, SetStateAction, useMemo } from \"react\";\nimport { MonacoLanguage } from \"../monaco\";\nimport {\n Anchor,\n Box,\n Button,\n Flex,\n Group,\n ScrollArea,\n Select,\n Stack,\n Text,\n} from \"@mantine/core\";\nimport { ConfirmUpdate } from \"./confirm\";\nimport { Bookmark, History } from \"lucide-react\";\nimport { ConfigGroup } from \"./group\";\nimport { UnsavedChanges } from \"./unsaved-changes\";\nimport { ConfigLayout } from \"./layout\";\nimport { SectionProps } from \"../section\";\n\nexport * from \"./confirm\";\nexport * from \"./group\";\nexport * from \"./item\";\nexport * from \"./layout\";\nexport * from \"./unsaved-changes\";\n\nexport interface ConfigFieldArgs {\n label?: string;\n description?: ReactNode;\n /** Use a selector instead of input */\n options?: { value: string; label?: string; icon?: ReactNode }[];\n placeholder?: string;\n hidden?: boolean;\n disabled?: boolean;\n}\n\nexport interface ConfigGroupArgs<T> {\n label: string;\n labelExtra?: ReactNode;\n icon?: ReactNode;\n description?: ReactNode;\n actions?: ReactNode;\n hidden?: boolean;\n labelHidden?: boolean;\n contentHidden?: boolean;\n fields: {\n [K in keyof Partial<T>]:\n | boolean\n | ConfigFieldArgs\n | ((value: T[K], set: (value: Partial<T>) => void) => ReactNode);\n };\n}\n\nexport interface ConfigProps<T> extends SectionProps {\n original: T;\n update: Partial<T>;\n setUpdate: React.Dispatch<SetStateAction<Partial<T>>>;\n disabled: boolean;\n onSave: () => Promise<unknown>;\n disableSidebar?: boolean;\n fileContentsLanguage?: MonacoLanguage;\n enableFancyToml?: boolean;\n groups: Record<\n string, // Section key\n ConfigGroupArgs<T>[] | false | undefined\n >;\n}\n\nexport function Config<T>({\n original,\n update,\n setUpdate,\n disabled,\n onSave,\n disableSidebar,\n fileContentsLanguage,\n enableFancyToml,\n groups: _groups,\n ...sectionProps\n}: ConfigProps<T>) {\n const changesMade = Object.keys(update).length ? true : false;\n const onConfirm = async () => {\n await onSave();\n setUpdate({});\n };\n const onReset = () => setUpdate({});\n\n const groups = useMemo(\n () => Object.entries(_groups).filter(([_, groupArgs]) => !!groupArgs),\n [_groups],\n );\n\n const GroupsComponent = useMemo(\n () =>\n groups.map(([group, groupArgs]) => {\n return (\n <Fragment key={group}>\n {group && (\n <Text visibleFrom=\"lg\" fz=\"h2\" tt=\"uppercase\" mt=\"xl\">\n {group}\n </Text>\n )}\n\n <Stack>\n {(groupArgs as ConfigGroupArgs<T>[])\n .filter(({ hidden }) => !hidden)\n .map(\n ({\n label,\n labelHidden,\n icon,\n labelExtra,\n actions,\n description,\n contentHidden,\n fields,\n }) => (\n <Stack\n key={group + label}\n id={group + label}\n p=\"xl\"\n gap=\"md\"\n className=\"bordered-light\"\n bdrs=\"md\"\n style={{ scrollMarginTop: 94 }}\n >\n {!labelHidden && (\n <Group justify=\"space-between\">\n <Stack gap=\"0\">\n <Group>\n {icon}\n <Text fz=\"h3\">{label}</Text>\n {labelExtra}\n </Group>\n {description && (\n <Text c=\"dimmed\">{description}</Text>\n )}\n </Stack>\n {actions}\n </Group>\n )}\n {!contentHidden && (\n <ConfigGroup\n config={original}\n update={update}\n setUpdate={(u) => setUpdate((p) => ({ ...p, ...u }))}\n fields={fields}\n disabled={disabled}\n />\n )}\n </Stack>\n ),\n )}\n </Stack>\n </Fragment>\n );\n }),\n [groups],\n );\n\n const SaveOrReset = ({\n unsavedIndicator,\n fullWidth,\n }: {\n unsavedIndicator?: boolean;\n fullWidth?: boolean;\n }) =>\n changesMade && (\n <>\n {unsavedIndicator && <UnsavedChanges fullWidth={fullWidth} />}\n <Button\n variant=\"outline\"\n onClick={onReset}\n disabled={disabled || !changesMade}\n leftSection={<History size=\"1rem\" />}\n fullWidth={fullWidth}\n w={fullWidth ? undefined : 100}\n >\n Reset\n </Button>\n <ConfirmUpdate\n original={original}\n update={update}\n onConfirm={onConfirm}\n disabled={disabled}\n fileContentsLanguage={fileContentsLanguage}\n fullWidth={fullWidth}\n enableFancyToml={enableFancyToml}\n />\n </>\n );\n\n const SaveOrResetComponent = changesMade && (\n <>\n <Group visibleFrom=\"xs\" justify=\"flex-end\">\n <SaveOrReset unsavedIndicator />\n </Group>\n <Stack hiddenFrom=\"xs\">\n <SaveOrReset unsavedIndicator fullWidth />\n </Stack>\n </>\n );\n\n return (\n <ConfigLayout SaveOrReset={SaveOrResetComponent} {...sectionProps}>\n {disableSidebar && (\n <>\n {GroupsComponent}\n {SaveOrResetComponent}\n </>\n )}\n {!disableSidebar && (\n <Flex w=\"100%\" gap=\"md\" direction={{ base: \"column\", lg: \"row\" }}>\n {/** SIDEBAR (LG) */}\n <Box\n visibleFrom=\"lg\"\n pos=\"relative\"\n className=\"bordered-light\"\n style={{\n borderLeftWidth: 0,\n borderBottomWidth: 0,\n borderTopRightRadius: \"var(--mantine-radius-md)\",\n }}\n >\n <Stack pos=\"sticky\" w={175} top={88} pb={24} m=\"lg\">\n {/** ANCHORS */}\n <ScrollArea\n mah={\n changesMade ? \"calc(100vh - 220px)\" : \"calc(100vh - 130px)\"\n }\n >\n <Stack>\n {groups\n .filter(([_, groupArgs]) => groupArgs)\n .map(([group, groupArgs]) => (\n <Stack key={group} gap=\"xs\">\n <Group justify=\"flex-end\" mr=\"md\" c=\"dimmed\">\n <Bookmark size=\"1rem\" />\n <Text tt=\"uppercase\">{group || \"GENERAL\"}</Text>\n </Group>\n <Stack gap=\"0.1rem\">\n {groupArgs &&\n groupArgs\n .filter((groupArgs) => !groupArgs.hidden)\n .map((groupArgs) => (\n <Button\n key={group + groupArgs.label}\n variant=\"subtle\"\n justify=\"flex-end\"\n size=\"sm\"\n fullWidth\n renderRoot={(props) => (\n <Anchor\n href={\"#\" + group + groupArgs.label}\n {...props}\n />\n )}\n >\n {groupArgs.label}\n </Button>\n ))}\n </Stack>\n </Stack>\n ))}\n </Stack>\n </ScrollArea>\n\n {/** SAVE */}\n <Stack gap=\"xs\">\n <SaveOrReset fullWidth />\n </Stack>\n </Stack>\n </Box>\n\n {/** SELECTOR (MOBILE) */}\n <Select\n hiddenFrom=\"lg\"\n className=\"select-nondimmed-placeholder\"\n placeholder=\"Go To\"\n leftSection={<Bookmark size=\"1rem\" />}\n value={null}\n data={groups\n .filter(([_, groupArgs]) => groupArgs)\n .map(([group, groupArgs]) => ({\n group,\n items: (groupArgs as ConfigGroupArgs<T>[]).map((arg) => ({\n label: arg.label,\n value: group + arg.label,\n })),\n }))}\n onChange={(group) => {\n if (!group) return;\n window.location.hash = group;\n }}\n />\n\n {/** CONTENT */}\n <Stack style={{ flexGrow: 1 }} gap=\"md\">\n {GroupsComponent}\n {SaveOrResetComponent}\n </Stack>\n </Flex>\n )}\n </ConfigLayout>\n );\n}\n"],"mappings":"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","names":["Fragment","groupArgs"]}
@@ -55,6 +55,7 @@ function DataTable({
55
55
  data,
56
56
  loading,
57
57
  onRowClick,
58
+ onRowContextMenu,
58
59
  noResults = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_core.Text, { c: "dimmed", children: "No results" }),
59
60
  sortDescFirst = false,
60
61
  defaultSort = [],
@@ -174,6 +175,7 @@ function DataTable({
174
175
  ) }) : rows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
175
176
  import_core.Table.Tr,
176
177
  {
178
+ onContextMenu: onRowContextMenu ? (e) => onRowContextMenu(row.original, e) : void 0,
177
179
  style: {
178
180
  cursor: onRowClick ? "pointer" : void 0,
179
181
  contentVisibility: "auto",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/data-table.tsx"],"sourcesContent":["import {\n Dispatch,\n ReactNode,\n SetStateAction,\n useEffect,\n useLayoutEffect,\n useState,\n} from \"react\";\nimport {\n Column,\n ColumnDef,\n columnVisibilityFeature,\n createSortedRowModel,\n flexRender,\n Row,\n RowData,\n RowSelectionState,\n rowSelectionFeature,\n rowSortingFeature,\n SortingState,\n sortFn_alphanumeric,\n sortFn_alphanumericCaseSensitive,\n sortFn_basic,\n sortFn_datetime,\n sortFn_text,\n sortFn_textCaseSensitive,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport {\n Box,\n BoxProps,\n Center,\n Checkbox,\n DefaultMantineColor,\n Group,\n HoverCard,\n Loader,\n Table,\n TableProps,\n Text,\n UnstyledButton,\n} from \"@mantine/core\";\nimport { ArrowDown, ArrowUp, Info, Minus } from \"lucide-react\";\n\n// All built-in sort fns are registered so consumer columns can keep\n// using `sortFn: \"auto\"` (the default) or any built-in name.\nconst features = tableFeatures({\n rowSortingFeature,\n rowSelectionFeature,\n columnVisibilityFeature,\n sortedRowModel: createSortedRowModel(),\n sortFns: {\n alphanumeric: sortFn_alphanumeric,\n alphanumericCaseSensitive: sortFn_alphanumericCaseSensitive,\n basic: sortFn_basic,\n datetime: sortFn_datetime,\n text: sortFn_text,\n textCaseSensitive: sortFn_textCaseSensitive,\n },\n});\n\n/** The table features `DataTable` is built with.\n * Use as the `TFeatures` generic on `ColumnDef` / `Column` etc. */\nexport type DataTableFeatures = typeof features;\n\nfunction loadStoredSorting(tableKey: string): SortingState | null {\n try {\n const stored = localStorage.getItem(\"data-table-\" + tableKey);\n return stored ? (JSON.parse(stored) as SortingState) : null;\n } catch {\n return null;\n }\n}\n\nexport interface DataTableProps<TData extends RowData, TValue = unknown>\n extends BoxProps {\n /** Unique key given to table so sorting can be remembered on local storage */\n tableKey: string;\n columns: (ColumnDef<DataTableFeatures, TData, TValue> | false | undefined)[];\n data: TData[];\n loading?: boolean;\n onRowClick?: (row: TData) => void;\n noResults?: ReactNode;\n defaultSort?: SortingState;\n sortDescFirst?: boolean;\n /** Sorting is handled externally (eg. server side).\n * The table still manages / persists the sorting state,\n * but does not apply it to the rows. */\n manualSorting?: boolean;\n /** Called with the sorting state whenever it changes.\n * Also called on mount with the initial state\n * (loaded from local storage when available). */\n onSortingStateChange?: (sorting: SortingState) => void;\n selectOptions?: {\n selectKey: (row: TData) => string;\n onSelect?: (selected: string[]) => void;\n state?: [RowSelectionState, Dispatch<SetStateAction<RowSelectionState>>];\n disableRow?: boolean | ((row: Row<DataTableFeatures, TData>) => boolean);\n color?: DefaultMantineColor;\n };\n caption?: string;\n tableProps?: TableProps;\n noBox?: boolean;\n noBorder?: boolean;\n}\n\nexport function DataTable<TData extends RowData, TValue>({\n tableKey,\n columns,\n data,\n loading,\n onRowClick,\n noResults = <Text c=\"dimmed\">No results</Text>,\n sortDescFirst = false,\n defaultSort = [],\n manualSorting,\n onSortingStateChange,\n selectOptions,\n caption,\n tableProps,\n noBox,\n noBorder,\n mah = \"max(150px, calc(100vh - 320px))\",\n ...boxProps\n}: DataTableProps<TData, TValue>) {\n // Initialized synchronously from local storage so the first render\n // (and any server side sorted query) already uses the persisted sort,\n // instead of flashing through the unsorted state.\n const [sorting, setSorting] = useState<SortingState>(\n () => loadStoredSorting(tableKey) ?? defaultSort,\n );\n const [prevTableKey, setPrevTableKey] = useState(tableKey);\n if (prevTableKey !== tableKey) {\n setPrevTableKey(tableKey);\n setSorting(loadStoredSorting(tableKey) ?? defaultSort);\n }\n\n // intentionally not initialized to clear selected values on table mount\n // could add some prop for adding default selected state to preserve between mounts\n const _internalState = useState<RowSelectionState>({});\n const [rowSelection, setRowSelection] = selectOptions?.state\n ? selectOptions.state\n : _internalState;\n\n const table = useTable({\n features,\n data,\n columns: columns.filter((c) => c) as any,\n onSortingChange: setSorting,\n manualSorting,\n state: {\n sorting,\n rowSelection,\n },\n sortDescFirst,\n onRowSelectionChange: setRowSelection,\n getRowId: selectOptions?.selectKey,\n enableRowSelection: selectOptions?.disableRow,\n });\n\n useEffect(() => {\n localStorage.setItem(\"data-table-\" + tableKey, JSON.stringify(sorting));\n }, [tableKey, sorting]);\n\n // Layout effect so the parent receives the initial (persisted) sorting\n // before any of its own passive effects run, ie before react-query\n // subscribes a server side sorted query using the pre-sort key.\n useLayoutEffect(() => {\n onSortingStateChange?.(sorting);\n }, [sorting]);\n\n useEffect(() => {\n selectOptions?.onSelect?.(Object.keys(rowSelection));\n }, [rowSelection]);\n\n const rows = table.getRowModel().rows;\n\n const tableNode = (\n <Table\n borderColor=\"accent-border\"\n captionSide=\"top\"\n stickyHeader\n {...tableProps}\n >\n {caption ? <Table.Caption>{caption}</Table.Caption> : null}\n\n <Table.Thead>\n {table.getHeaderGroups().map((hg, i) => (\n <Table.Tr key={hg.id}>\n {i === 0 && selectOptions && (\n <Table.Th\n onClick={() =>\n selectOptions.disableRow !== true &&\n table.toggleAllRowsSelected()\n }\n style={{\n cursor: \"pointer\",\n borderColor: \"var(--mantine-color-accent-border-0)\",\n borderWidth: 0,\n borderRightWidth: 1,\n borderStyle: \"solid\",\n }}\n >\n <Checkbox\n color={selectOptions.color ?? \"Neutral\"}\n disabled={selectOptions.disableRow === true}\n checked={table.getIsAllRowsSelected()}\n indeterminate={\n // v9: getIsSomeRowsSelected is true even when all are selected\n table.getIsSomeRowsSelected() && !table.getIsAllRowsSelected()\n }\n />\n </Table.Th>\n )}\n {hg.headers.map((header, i) => {\n // const canSort = header.column.getCanSort();\n // const sortState = header.column.getIsSorted();\n return (\n <Table.Th\n key={header.id}\n px=\"md\"\n style={{\n cursor: \"pointer\",\n borderColor: \"var(--mantine-color-accent-border-0)\",\n borderWidth: 0,\n borderRightWidth: i < hg.headers.length - 1 ? 1 : 0,\n borderStyle: \"solid\",\n }}\n >\n {header.isPlaceholder ? null : (\n <Text fw={600} size=\"sm\" lineClamp={1}>\n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n </Text>\n )}\n </Table.Th>\n );\n })}\n </Table.Tr>\n ))}\n </Table.Thead>\n\n <Table.Tbody>\n {loading ? (\n <Table.Tr>\n <Table.Td\n colSpan={\n table.getAllLeafColumns().length + (selectOptions ? 1 : 0)\n }\n >\n <Group justify=\"center\" py=\"lg\">\n <Loader size=\"sm\" />\n </Group>\n </Table.Td>\n </Table.Tr>\n ) : rows.length === 0 ? (\n <Table.Tr>\n <Table.Td\n colSpan={\n table.getAllLeafColumns().length + (selectOptions ? 1 : 0)\n }\n >\n <Group justify=\"center\" py=\"lg\">\n {noResults}\n </Group>\n </Table.Td>\n </Table.Tr>\n ) : (\n rows.map((row) => (\n <Table.Tr\n key={row.id}\n style={{\n cursor: onRowClick ? \"pointer\" : undefined,\n contentVisibility: \"auto\",\n containIntrinsicSize: \"auto 2em\",\n }}\n >\n {selectOptions && (\n <Table.Td onClick={() => row.toggleSelected()}>\n <Checkbox\n aria-label=\"Select row\"\n color={selectOptions.color ?? \"Neutral\"}\n disabled={!row.getCanSelect()}\n checked={row.getIsSelected()}\n />\n </Table.Td>\n )}\n {row.getVisibleCells().map((cell) => (\n <Table.Td\n key={cell.id}\n onClick={\n onRowClick ? () => onRowClick(row.original) : undefined\n }\n style={{ flexWrap: \"nowrap\", textWrap: \"nowrap\" }}\n >\n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n </Table.Td>\n ))}\n </Table.Tr>\n ))\n )}\n </Table.Tbody>\n </Table>\n );\n\n if (noBox) {\n return tableNode;\n } else {\n return (\n <Box\n p={noBorder ? undefined : \"lg\"}\n pt=\"0\"\n className={noBorder ? undefined : \"bordered-light\"}\n bdrs=\"md\"\n w=\"100%\"\n mah={mah}\n style={{ overflow: \"auto\" }}\n {...boxProps}\n >\n {tableNode}\n </Box>\n );\n }\n}\n\nexport const SortableHeader = <T extends RowData, V>({\n column,\n title,\n description,\n sortDescFirst,\n disabled,\n}: {\n column: Column<DataTableFeatures, T, V>;\n title: string;\n description?: ReactNode;\n sortDescFirst?: boolean;\n disabled?: boolean;\n}) => {\n if (disabled || !column.getCanSort()) {\n return (\n <Group justify=\"start\" gap=\"xs\" wrap=\"nowrap\" miw=\"120\" w=\"fit-content\">\n <Text fw={600} size=\"sm\" lineClamp={1}>\n {title}\n </Text>\n {description && (\n <HoverCard offset={10}>\n <HoverCard.Target>\n <Info size=\"1rem\" />\n </HoverCard.Target>\n <HoverCard.Dropdown>\n <Text>{description}</Text>\n </HoverCard.Dropdown>\n </HoverCard>\n )}\n </Group>\n );\n }\n return (\n <UnstyledButton\n onClick={column.getToggleSortingHandler()}\n style={{ width: \"100%\" }}\n >\n <Group justify=\"space-between\" gap=\"sm\" wrap=\"nowrap\">\n <Group justify=\"start\" gap=\"xs\" wrap=\"nowrap\" miw=\"120\" w=\"fit-content\">\n <Text fw={600} size=\"sm\" lineClamp={1}>\n {title}\n </Text>\n {description && (\n <HoverCard offset={10}>\n <HoverCard.Target>\n <Info size=\"1rem\" />\n </HoverCard.Target>\n <HoverCard.Dropdown>\n <Text>{description}</Text>\n </HoverCard.Dropdown>\n </HoverCard>\n )}\n </Group>\n <Center>\n <SortIcon\n state={column.getIsSorted()}\n sortDescFirst={sortDescFirst}\n />\n </Center>\n </Group>\n </UnstyledButton>\n );\n};\n\nfunction SortIcon({\n state,\n sortDescFirst,\n}: {\n state: false | \"asc\" | \"desc\";\n sortDescFirst?: boolean;\n}) {\n if (state === \"asc\")\n return sortDescFirst ? <ArrowUp size={14} /> : <ArrowDown size={14} />;\n if (state === \"desc\")\n return sortDescFirst ? <ArrowDown size={14} /> : <ArrowUp size={14} />;\n return <Minus size={14} />;\n}\n"],"mappings":"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","names":["i"]}
1
+ {"version":3,"sources":["../../src/components/data-table.tsx"],"sourcesContent":["import {\n Dispatch,\n MouseEvent,\n ReactNode,\n SetStateAction,\n useEffect,\n useLayoutEffect,\n useState,\n} from \"react\";\nimport {\n Column,\n ColumnDef,\n columnVisibilityFeature,\n createSortedRowModel,\n flexRender,\n Row,\n RowData,\n RowSelectionState,\n rowSelectionFeature,\n rowSortingFeature,\n SortingState,\n sortFn_alphanumeric,\n sortFn_alphanumericCaseSensitive,\n sortFn_basic,\n sortFn_datetime,\n sortFn_text,\n sortFn_textCaseSensitive,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport {\n Box,\n BoxProps,\n Center,\n Checkbox,\n DefaultMantineColor,\n Group,\n HoverCard,\n Loader,\n Table,\n TableProps,\n Text,\n UnstyledButton,\n} from \"@mantine/core\";\nimport { ArrowDown, ArrowUp, Info, Minus } from \"lucide-react\";\n\n// All built-in sort fns are registered so consumer columns can keep\n// using `sortFn: \"auto\"` (the default) or any built-in name.\nconst features = tableFeatures({\n rowSortingFeature,\n rowSelectionFeature,\n columnVisibilityFeature,\n sortedRowModel: createSortedRowModel(),\n sortFns: {\n alphanumeric: sortFn_alphanumeric,\n alphanumericCaseSensitive: sortFn_alphanumericCaseSensitive,\n basic: sortFn_basic,\n datetime: sortFn_datetime,\n text: sortFn_text,\n textCaseSensitive: sortFn_textCaseSensitive,\n },\n});\n\n/** The table features `DataTable` is built with.\n * Use as the `TFeatures` generic on `ColumnDef` / `Column` etc. */\nexport type DataTableFeatures = typeof features;\n\nfunction loadStoredSorting(tableKey: string): SortingState | null {\n try {\n const stored = localStorage.getItem(\"data-table-\" + tableKey);\n return stored ? (JSON.parse(stored) as SortingState) : null;\n } catch {\n return null;\n }\n}\n\nexport interface DataTableProps<TData extends RowData, TValue = unknown>\n extends BoxProps {\n /** Unique key given to table so sorting can be remembered on local storage */\n tableKey: string;\n columns: (ColumnDef<DataTableFeatures, TData, TValue> | false | undefined)[];\n data: TData[];\n loading?: boolean;\n onRowClick?: (row: TData) => void;\n /** Called when a row is right clicked. The consumer decides whether to\n * `preventDefault` the native context menu. */\n onRowContextMenu?: (row: TData, e: MouseEvent<HTMLTableRowElement>) => void;\n noResults?: ReactNode;\n defaultSort?: SortingState;\n sortDescFirst?: boolean;\n /** Sorting is handled externally (eg. server side).\n * The table still manages / persists the sorting state,\n * but does not apply it to the rows. */\n manualSorting?: boolean;\n /** Called with the sorting state whenever it changes.\n * Also called on mount with the initial state\n * (loaded from local storage when available). */\n onSortingStateChange?: (sorting: SortingState) => void;\n selectOptions?: {\n selectKey: (row: TData) => string;\n onSelect?: (selected: string[]) => void;\n state?: [RowSelectionState, Dispatch<SetStateAction<RowSelectionState>>];\n disableRow?: boolean | ((row: Row<DataTableFeatures, TData>) => boolean);\n color?: DefaultMantineColor;\n };\n caption?: string;\n tableProps?: TableProps;\n noBox?: boolean;\n noBorder?: boolean;\n}\n\nexport function DataTable<TData extends RowData, TValue>({\n tableKey,\n columns,\n data,\n loading,\n onRowClick,\n onRowContextMenu,\n noResults = <Text c=\"dimmed\">No results</Text>,\n sortDescFirst = false,\n defaultSort = [],\n manualSorting,\n onSortingStateChange,\n selectOptions,\n caption,\n tableProps,\n noBox,\n noBorder,\n mah = \"max(150px, calc(100vh - 320px))\",\n ...boxProps\n}: DataTableProps<TData, TValue>) {\n // Initialized synchronously from local storage so the first render\n // (and any server side sorted query) already uses the persisted sort,\n // instead of flashing through the unsorted state.\n const [sorting, setSorting] = useState<SortingState>(\n () => loadStoredSorting(tableKey) ?? defaultSort,\n );\n const [prevTableKey, setPrevTableKey] = useState(tableKey);\n if (prevTableKey !== tableKey) {\n setPrevTableKey(tableKey);\n setSorting(loadStoredSorting(tableKey) ?? defaultSort);\n }\n\n // intentionally not initialized to clear selected values on table mount\n // could add some prop for adding default selected state to preserve between mounts\n const _internalState = useState<RowSelectionState>({});\n const [rowSelection, setRowSelection] = selectOptions?.state\n ? selectOptions.state\n : _internalState;\n\n const table = useTable({\n features,\n data,\n columns: columns.filter((c) => c) as any,\n onSortingChange: setSorting,\n manualSorting,\n state: {\n sorting,\n rowSelection,\n },\n sortDescFirst,\n onRowSelectionChange: setRowSelection,\n getRowId: selectOptions?.selectKey,\n enableRowSelection: selectOptions?.disableRow,\n });\n\n useEffect(() => {\n localStorage.setItem(\"data-table-\" + tableKey, JSON.stringify(sorting));\n }, [tableKey, sorting]);\n\n // Layout effect so the parent receives the initial (persisted) sorting\n // before any of its own passive effects run, ie before react-query\n // subscribes a server side sorted query using the pre-sort key.\n useLayoutEffect(() => {\n onSortingStateChange?.(sorting);\n }, [sorting]);\n\n useEffect(() => {\n selectOptions?.onSelect?.(Object.keys(rowSelection));\n }, [rowSelection]);\n\n const rows = table.getRowModel().rows;\n\n const tableNode = (\n <Table\n borderColor=\"accent-border\"\n captionSide=\"top\"\n stickyHeader\n {...tableProps}\n >\n {caption ? <Table.Caption>{caption}</Table.Caption> : null}\n\n <Table.Thead>\n {table.getHeaderGroups().map((hg, i) => (\n <Table.Tr key={hg.id}>\n {i === 0 && selectOptions && (\n <Table.Th\n onClick={() =>\n selectOptions.disableRow !== true &&\n table.toggleAllRowsSelected()\n }\n style={{\n cursor: \"pointer\",\n borderColor: \"var(--mantine-color-accent-border-0)\",\n borderWidth: 0,\n borderRightWidth: 1,\n borderStyle: \"solid\",\n }}\n >\n <Checkbox\n color={selectOptions.color ?? \"Neutral\"}\n disabled={selectOptions.disableRow === true}\n checked={table.getIsAllRowsSelected()}\n indeterminate={\n // v9: getIsSomeRowsSelected is true even when all are selected\n table.getIsSomeRowsSelected() && !table.getIsAllRowsSelected()\n }\n />\n </Table.Th>\n )}\n {hg.headers.map((header, i) => {\n // const canSort = header.column.getCanSort();\n // const sortState = header.column.getIsSorted();\n return (\n <Table.Th\n key={header.id}\n px=\"md\"\n style={{\n cursor: \"pointer\",\n borderColor: \"var(--mantine-color-accent-border-0)\",\n borderWidth: 0,\n borderRightWidth: i < hg.headers.length - 1 ? 1 : 0,\n borderStyle: \"solid\",\n }}\n >\n {header.isPlaceholder ? null : (\n <Text fw={600} size=\"sm\" lineClamp={1}>\n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n </Text>\n )}\n </Table.Th>\n );\n })}\n </Table.Tr>\n ))}\n </Table.Thead>\n\n <Table.Tbody>\n {loading ? (\n <Table.Tr>\n <Table.Td\n colSpan={\n table.getAllLeafColumns().length + (selectOptions ? 1 : 0)\n }\n >\n <Group justify=\"center\" py=\"lg\">\n <Loader size=\"sm\" />\n </Group>\n </Table.Td>\n </Table.Tr>\n ) : rows.length === 0 ? (\n <Table.Tr>\n <Table.Td\n colSpan={\n table.getAllLeafColumns().length + (selectOptions ? 1 : 0)\n }\n >\n <Group justify=\"center\" py=\"lg\">\n {noResults}\n </Group>\n </Table.Td>\n </Table.Tr>\n ) : (\n rows.map((row) => (\n <Table.Tr\n key={row.id}\n onContextMenu={\n onRowContextMenu\n ? (e) => onRowContextMenu(row.original, e)\n : undefined\n }\n style={{\n cursor: onRowClick ? \"pointer\" : undefined,\n contentVisibility: \"auto\",\n containIntrinsicSize: \"auto 2em\",\n }}\n >\n {selectOptions && (\n <Table.Td onClick={() => row.toggleSelected()}>\n <Checkbox\n aria-label=\"Select row\"\n color={selectOptions.color ?? \"Neutral\"}\n disabled={!row.getCanSelect()}\n checked={row.getIsSelected()}\n />\n </Table.Td>\n )}\n {row.getVisibleCells().map((cell) => (\n <Table.Td\n key={cell.id}\n onClick={\n onRowClick ? () => onRowClick(row.original) : undefined\n }\n style={{ flexWrap: \"nowrap\", textWrap: \"nowrap\" }}\n >\n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n </Table.Td>\n ))}\n </Table.Tr>\n ))\n )}\n </Table.Tbody>\n </Table>\n );\n\n if (noBox) {\n return tableNode;\n } else {\n return (\n <Box\n p={noBorder ? undefined : \"lg\"}\n pt=\"0\"\n className={noBorder ? undefined : \"bordered-light\"}\n bdrs=\"md\"\n w=\"100%\"\n mah={mah}\n style={{ overflow: \"auto\" }}\n {...boxProps}\n >\n {tableNode}\n </Box>\n );\n }\n}\n\nexport const SortableHeader = <T extends RowData, V>({\n column,\n title,\n description,\n sortDescFirst,\n disabled,\n}: {\n column: Column<DataTableFeatures, T, V>;\n title: string;\n description?: ReactNode;\n sortDescFirst?: boolean;\n disabled?: boolean;\n}) => {\n if (disabled || !column.getCanSort()) {\n return (\n <Group justify=\"start\" gap=\"xs\" wrap=\"nowrap\" miw=\"120\" w=\"fit-content\">\n <Text fw={600} size=\"sm\" lineClamp={1}>\n {title}\n </Text>\n {description && (\n <HoverCard offset={10}>\n <HoverCard.Target>\n <Info size=\"1rem\" />\n </HoverCard.Target>\n <HoverCard.Dropdown>\n <Text>{description}</Text>\n </HoverCard.Dropdown>\n </HoverCard>\n )}\n </Group>\n );\n }\n return (\n <UnstyledButton\n onClick={column.getToggleSortingHandler()}\n style={{ width: \"100%\" }}\n >\n <Group justify=\"space-between\" gap=\"sm\" wrap=\"nowrap\">\n <Group justify=\"start\" gap=\"xs\" wrap=\"nowrap\" miw=\"120\" w=\"fit-content\">\n <Text fw={600} size=\"sm\" lineClamp={1}>\n {title}\n </Text>\n {description && (\n <HoverCard offset={10}>\n <HoverCard.Target>\n <Info size=\"1rem\" />\n </HoverCard.Target>\n <HoverCard.Dropdown>\n <Text>{description}</Text>\n </HoverCard.Dropdown>\n </HoverCard>\n )}\n </Group>\n <Center>\n <SortIcon\n state={column.getIsSorted()}\n sortDescFirst={sortDescFirst}\n />\n </Center>\n </Group>\n </UnstyledButton>\n );\n};\n\nfunction SortIcon({\n state,\n sortDescFirst,\n}: {\n state: false | \"asc\" | \"desc\";\n sortDescFirst?: boolean;\n}) {\n if (state === \"asc\")\n return sortDescFirst ? <ArrowUp size={14} /> : <ArrowDown size={14} />;\n if (state === \"desc\")\n return sortDescFirst ? <ArrowDown size={14} /> : <ArrowUp size={14} />;\n return <Minus size={14} />;\n}\n"],"mappings":"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","names":["i"]}
@@ -1,4 +1,4 @@
1
- import { Dispatch, ReactNode, SetStateAction } from "react";
1
+ import { Dispatch, MouseEvent, ReactNode, SetStateAction } from "react";
2
2
  import { Column, ColumnDef, Row, RowData, RowSelectionState, SortingState } from "@tanstack/react-table";
3
3
  import { BoxProps, DefaultMantineColor, TableProps } from "@mantine/core";
4
4
  declare const features: {
@@ -25,6 +25,9 @@ export interface DataTableProps<TData extends RowData, TValue = unknown> extends
25
25
  data: TData[];
26
26
  loading?: boolean;
27
27
  onRowClick?: (row: TData) => void;
28
+ /** Called when a row is right clicked. The consumer decides whether to
29
+ * `preventDefault` the native context menu. */
30
+ onRowContextMenu?: (row: TData, e: MouseEvent<HTMLTableRowElement>) => void;
28
31
  noResults?: ReactNode;
29
32
  defaultSort?: SortingState;
30
33
  sortDescFirst?: boolean;
@@ -48,7 +51,7 @@ export interface DataTableProps<TData extends RowData, TValue = unknown> extends
48
51
  noBox?: boolean;
49
52
  noBorder?: boolean;
50
53
  }
51
- export declare function DataTable<TData extends RowData, TValue>({ tableKey, columns, data, loading, onRowClick, noResults, sortDescFirst, defaultSort, manualSorting, onSortingStateChange, selectOptions, caption, tableProps, noBox, noBorder, mah, ...boxProps }: DataTableProps<TData, TValue>): import("react").JSX.Element;
54
+ export declare function DataTable<TData extends RowData, TValue>({ tableKey, columns, data, loading, onRowClick, onRowContextMenu, noResults, sortDescFirst, defaultSort, manualSorting, onSortingStateChange, selectOptions, caption, tableProps, noBox, noBorder, mah, ...boxProps }: DataTableProps<TData, TValue>): import("react").JSX.Element;
52
55
  export declare const SortableHeader: <T extends RowData, V>({ column, title, description, sortDescFirst, disabled, }: {
53
56
  column: Column<DataTableFeatures, T, V>;
54
57
  title: string;
@@ -1 +1 @@
1
- {"version":3,"file":"data-table.d.ts","sourceRoot":"","sources":["../../src/components/data-table.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,SAAS,EACT,cAAc,EAIf,MAAM,OAAO,CAAC;AACf,OAAO,EACL,MAAM,EACN,SAAS,EAIT,GAAG,EACH,OAAO,EACP,iBAAiB,EAGjB,YAAY,EASb,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAEL,QAAQ,EAGR,mBAAmB,EAKnB,UAAU,EAGX,MAAM,eAAe,CAAC;AAKvB,QAAA,MAAM,QAAQ;;;;;;QAMV,YAAY;QACZ,yBAAyB;QACzB,KAAK;QACL,QAAQ;QACR,IAAI;QACJ,iBAAiB;;CAEnB,CAAC;AAEH;mEACmE;AACnE,MAAM,MAAM,iBAAiB,GAAG,OAAO,QAAQ,CAAC;AAWhD,MAAM,WAAW,cAAc,CAAC,KAAK,SAAS,OAAO,EAAE,MAAM,GAAG,OAAO,CACrE,SAAQ,QAAQ;IAChB,8EAA8E;IAC9E,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,CAAC,SAAS,CAAC,iBAAiB,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,KAAK,GAAG,SAAS,CAAC,EAAE,CAAC;IAC7E,IAAI,EAAE,KAAK,EAAE,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAC;IAClC,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,WAAW,CAAC,EAAE,YAAY,CAAC;IAC3B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;4CAEwC;IACxC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;qDAEiD;IACjD,oBAAoB,CAAC,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,CAAC;IACvD,aAAa,CAAC,EAAE;QACd,SAAS,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,MAAM,CAAC;QAClC,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;QACxC,KAAK,CAAC,EAAE,CAAC,iBAAiB,EAAE,QAAQ,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC;QACzE,UAAU,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,iBAAiB,EAAE,KAAK,CAAC,KAAK,OAAO,CAAC,CAAC;QACzE,KAAK,CAAC,EAAE,mBAAmB,CAAC;KAC7B,CAAC;IACF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,SAAS,CAAC,KAAK,SAAS,OAAO,EAAE,MAAM,EAAE,EACvD,QAAQ,EACR,OAAO,EACP,IAAI,EACJ,OAAO,EACP,UAAU,EACV,SAA8C,EAC9C,aAAqB,EACrB,WAAgB,EAChB,aAAa,EACb,oBAAoB,EACpB,aAAa,EACb,OAAO,EACP,UAAU,EACV,KAAK,EACL,QAAQ,EACR,GAAuC,EACvC,GAAG,QAAQ,EACZ,EAAE,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,+BAyM/B;AAED,eAAO,MAAM,cAAc,GAAI,CAAC,SAAS,OAAO,EAAE,CAAC,4DAMhD;IACD,MAAM,EAAE,MAAM,CAAC,iBAAiB,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,gCAkDA,CAAC"}
1
+ {"version":3,"file":"data-table.d.ts","sourceRoot":"","sources":["../../src/components/data-table.tsx"],"names":[],"mappings":"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"}
@@ -59,6 +59,7 @@ function DataTable({
59
59
  data,
60
60
  loading,
61
61
  onRowClick,
62
+ onRowContextMenu,
62
63
  noResults = /* @__PURE__ */ jsx(Text, { c: "dimmed", children: "No results" }),
63
64
  sortDescFirst = false,
64
65
  defaultSort = [],
@@ -178,6 +179,7 @@ function DataTable({
178
179
  ) }) : rows.map((row) => /* @__PURE__ */ jsxs(
179
180
  Table.Tr,
180
181
  {
182
+ onContextMenu: onRowContextMenu ? (e) => onRowContextMenu(row.original, e) : void 0,
181
183
  style: {
182
184
  cursor: onRowClick ? "pointer" : void 0,
183
185
  contentVisibility: "auto",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/data-table.tsx"],"sourcesContent":["import {\n Dispatch,\n ReactNode,\n SetStateAction,\n useEffect,\n useLayoutEffect,\n useState,\n} from \"react\";\nimport {\n Column,\n ColumnDef,\n columnVisibilityFeature,\n createSortedRowModel,\n flexRender,\n Row,\n RowData,\n RowSelectionState,\n rowSelectionFeature,\n rowSortingFeature,\n SortingState,\n sortFn_alphanumeric,\n sortFn_alphanumericCaseSensitive,\n sortFn_basic,\n sortFn_datetime,\n sortFn_text,\n sortFn_textCaseSensitive,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport {\n Box,\n BoxProps,\n Center,\n Checkbox,\n DefaultMantineColor,\n Group,\n HoverCard,\n Loader,\n Table,\n TableProps,\n Text,\n UnstyledButton,\n} from \"@mantine/core\";\nimport { ArrowDown, ArrowUp, Info, Minus } from \"lucide-react\";\n\n// All built-in sort fns are registered so consumer columns can keep\n// using `sortFn: \"auto\"` (the default) or any built-in name.\nconst features = tableFeatures({\n rowSortingFeature,\n rowSelectionFeature,\n columnVisibilityFeature,\n sortedRowModel: createSortedRowModel(),\n sortFns: {\n alphanumeric: sortFn_alphanumeric,\n alphanumericCaseSensitive: sortFn_alphanumericCaseSensitive,\n basic: sortFn_basic,\n datetime: sortFn_datetime,\n text: sortFn_text,\n textCaseSensitive: sortFn_textCaseSensitive,\n },\n});\n\n/** The table features `DataTable` is built with.\n * Use as the `TFeatures` generic on `ColumnDef` / `Column` etc. */\nexport type DataTableFeatures = typeof features;\n\nfunction loadStoredSorting(tableKey: string): SortingState | null {\n try {\n const stored = localStorage.getItem(\"data-table-\" + tableKey);\n return stored ? (JSON.parse(stored) as SortingState) : null;\n } catch {\n return null;\n }\n}\n\nexport interface DataTableProps<TData extends RowData, TValue = unknown>\n extends BoxProps {\n /** Unique key given to table so sorting can be remembered on local storage */\n tableKey: string;\n columns: (ColumnDef<DataTableFeatures, TData, TValue> | false | undefined)[];\n data: TData[];\n loading?: boolean;\n onRowClick?: (row: TData) => void;\n noResults?: ReactNode;\n defaultSort?: SortingState;\n sortDescFirst?: boolean;\n /** Sorting is handled externally (eg. server side).\n * The table still manages / persists the sorting state,\n * but does not apply it to the rows. */\n manualSorting?: boolean;\n /** Called with the sorting state whenever it changes.\n * Also called on mount with the initial state\n * (loaded from local storage when available). */\n onSortingStateChange?: (sorting: SortingState) => void;\n selectOptions?: {\n selectKey: (row: TData) => string;\n onSelect?: (selected: string[]) => void;\n state?: [RowSelectionState, Dispatch<SetStateAction<RowSelectionState>>];\n disableRow?: boolean | ((row: Row<DataTableFeatures, TData>) => boolean);\n color?: DefaultMantineColor;\n };\n caption?: string;\n tableProps?: TableProps;\n noBox?: boolean;\n noBorder?: boolean;\n}\n\nexport function DataTable<TData extends RowData, TValue>({\n tableKey,\n columns,\n data,\n loading,\n onRowClick,\n noResults = <Text c=\"dimmed\">No results</Text>,\n sortDescFirst = false,\n defaultSort = [],\n manualSorting,\n onSortingStateChange,\n selectOptions,\n caption,\n tableProps,\n noBox,\n noBorder,\n mah = \"max(150px, calc(100vh - 320px))\",\n ...boxProps\n}: DataTableProps<TData, TValue>) {\n // Initialized synchronously from local storage so the first render\n // (and any server side sorted query) already uses the persisted sort,\n // instead of flashing through the unsorted state.\n const [sorting, setSorting] = useState<SortingState>(\n () => loadStoredSorting(tableKey) ?? defaultSort,\n );\n const [prevTableKey, setPrevTableKey] = useState(tableKey);\n if (prevTableKey !== tableKey) {\n setPrevTableKey(tableKey);\n setSorting(loadStoredSorting(tableKey) ?? defaultSort);\n }\n\n // intentionally not initialized to clear selected values on table mount\n // could add some prop for adding default selected state to preserve between mounts\n const _internalState = useState<RowSelectionState>({});\n const [rowSelection, setRowSelection] = selectOptions?.state\n ? selectOptions.state\n : _internalState;\n\n const table = useTable({\n features,\n data,\n columns: columns.filter((c) => c) as any,\n onSortingChange: setSorting,\n manualSorting,\n state: {\n sorting,\n rowSelection,\n },\n sortDescFirst,\n onRowSelectionChange: setRowSelection,\n getRowId: selectOptions?.selectKey,\n enableRowSelection: selectOptions?.disableRow,\n });\n\n useEffect(() => {\n localStorage.setItem(\"data-table-\" + tableKey, JSON.stringify(sorting));\n }, [tableKey, sorting]);\n\n // Layout effect so the parent receives the initial (persisted) sorting\n // before any of its own passive effects run, ie before react-query\n // subscribes a server side sorted query using the pre-sort key.\n useLayoutEffect(() => {\n onSortingStateChange?.(sorting);\n }, [sorting]);\n\n useEffect(() => {\n selectOptions?.onSelect?.(Object.keys(rowSelection));\n }, [rowSelection]);\n\n const rows = table.getRowModel().rows;\n\n const tableNode = (\n <Table\n borderColor=\"accent-border\"\n captionSide=\"top\"\n stickyHeader\n {...tableProps}\n >\n {caption ? <Table.Caption>{caption}</Table.Caption> : null}\n\n <Table.Thead>\n {table.getHeaderGroups().map((hg, i) => (\n <Table.Tr key={hg.id}>\n {i === 0 && selectOptions && (\n <Table.Th\n onClick={() =>\n selectOptions.disableRow !== true &&\n table.toggleAllRowsSelected()\n }\n style={{\n cursor: \"pointer\",\n borderColor: \"var(--mantine-color-accent-border-0)\",\n borderWidth: 0,\n borderRightWidth: 1,\n borderStyle: \"solid\",\n }}\n >\n <Checkbox\n color={selectOptions.color ?? \"Neutral\"}\n disabled={selectOptions.disableRow === true}\n checked={table.getIsAllRowsSelected()}\n indeterminate={\n // v9: getIsSomeRowsSelected is true even when all are selected\n table.getIsSomeRowsSelected() && !table.getIsAllRowsSelected()\n }\n />\n </Table.Th>\n )}\n {hg.headers.map((header, i) => {\n // const canSort = header.column.getCanSort();\n // const sortState = header.column.getIsSorted();\n return (\n <Table.Th\n key={header.id}\n px=\"md\"\n style={{\n cursor: \"pointer\",\n borderColor: \"var(--mantine-color-accent-border-0)\",\n borderWidth: 0,\n borderRightWidth: i < hg.headers.length - 1 ? 1 : 0,\n borderStyle: \"solid\",\n }}\n >\n {header.isPlaceholder ? null : (\n <Text fw={600} size=\"sm\" lineClamp={1}>\n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n </Text>\n )}\n </Table.Th>\n );\n })}\n </Table.Tr>\n ))}\n </Table.Thead>\n\n <Table.Tbody>\n {loading ? (\n <Table.Tr>\n <Table.Td\n colSpan={\n table.getAllLeafColumns().length + (selectOptions ? 1 : 0)\n }\n >\n <Group justify=\"center\" py=\"lg\">\n <Loader size=\"sm\" />\n </Group>\n </Table.Td>\n </Table.Tr>\n ) : rows.length === 0 ? (\n <Table.Tr>\n <Table.Td\n colSpan={\n table.getAllLeafColumns().length + (selectOptions ? 1 : 0)\n }\n >\n <Group justify=\"center\" py=\"lg\">\n {noResults}\n </Group>\n </Table.Td>\n </Table.Tr>\n ) : (\n rows.map((row) => (\n <Table.Tr\n key={row.id}\n style={{\n cursor: onRowClick ? \"pointer\" : undefined,\n contentVisibility: \"auto\",\n containIntrinsicSize: \"auto 2em\",\n }}\n >\n {selectOptions && (\n <Table.Td onClick={() => row.toggleSelected()}>\n <Checkbox\n aria-label=\"Select row\"\n color={selectOptions.color ?? \"Neutral\"}\n disabled={!row.getCanSelect()}\n checked={row.getIsSelected()}\n />\n </Table.Td>\n )}\n {row.getVisibleCells().map((cell) => (\n <Table.Td\n key={cell.id}\n onClick={\n onRowClick ? () => onRowClick(row.original) : undefined\n }\n style={{ flexWrap: \"nowrap\", textWrap: \"nowrap\" }}\n >\n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n </Table.Td>\n ))}\n </Table.Tr>\n ))\n )}\n </Table.Tbody>\n </Table>\n );\n\n if (noBox) {\n return tableNode;\n } else {\n return (\n <Box\n p={noBorder ? undefined : \"lg\"}\n pt=\"0\"\n className={noBorder ? undefined : \"bordered-light\"}\n bdrs=\"md\"\n w=\"100%\"\n mah={mah}\n style={{ overflow: \"auto\" }}\n {...boxProps}\n >\n {tableNode}\n </Box>\n );\n }\n}\n\nexport const SortableHeader = <T extends RowData, V>({\n column,\n title,\n description,\n sortDescFirst,\n disabled,\n}: {\n column: Column<DataTableFeatures, T, V>;\n title: string;\n description?: ReactNode;\n sortDescFirst?: boolean;\n disabled?: boolean;\n}) => {\n if (disabled || !column.getCanSort()) {\n return (\n <Group justify=\"start\" gap=\"xs\" wrap=\"nowrap\" miw=\"120\" w=\"fit-content\">\n <Text fw={600} size=\"sm\" lineClamp={1}>\n {title}\n </Text>\n {description && (\n <HoverCard offset={10}>\n <HoverCard.Target>\n <Info size=\"1rem\" />\n </HoverCard.Target>\n <HoverCard.Dropdown>\n <Text>{description}</Text>\n </HoverCard.Dropdown>\n </HoverCard>\n )}\n </Group>\n );\n }\n return (\n <UnstyledButton\n onClick={column.getToggleSortingHandler()}\n style={{ width: \"100%\" }}\n >\n <Group justify=\"space-between\" gap=\"sm\" wrap=\"nowrap\">\n <Group justify=\"start\" gap=\"xs\" wrap=\"nowrap\" miw=\"120\" w=\"fit-content\">\n <Text fw={600} size=\"sm\" lineClamp={1}>\n {title}\n </Text>\n {description && (\n <HoverCard offset={10}>\n <HoverCard.Target>\n <Info size=\"1rem\" />\n </HoverCard.Target>\n <HoverCard.Dropdown>\n <Text>{description}</Text>\n </HoverCard.Dropdown>\n </HoverCard>\n )}\n </Group>\n <Center>\n <SortIcon\n state={column.getIsSorted()}\n sortDescFirst={sortDescFirst}\n />\n </Center>\n </Group>\n </UnstyledButton>\n );\n};\n\nfunction SortIcon({\n state,\n sortDescFirst,\n}: {\n state: false | \"asc\" | \"desc\";\n sortDescFirst?: boolean;\n}) {\n if (state === \"asc\")\n return sortDescFirst ? <ArrowUp size={14} /> : <ArrowDown size={14} />;\n if (state === \"desc\")\n return sortDescFirst ? <ArrowDown size={14} /> : <ArrowUp size={14} />;\n return <Minus size={14} />;\n}\n"],"mappings":"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","names":["i"]}
1
+ {"version":3,"sources":["../../src/components/data-table.tsx"],"sourcesContent":["import {\n Dispatch,\n MouseEvent,\n ReactNode,\n SetStateAction,\n useEffect,\n useLayoutEffect,\n useState,\n} from \"react\";\nimport {\n Column,\n ColumnDef,\n columnVisibilityFeature,\n createSortedRowModel,\n flexRender,\n Row,\n RowData,\n RowSelectionState,\n rowSelectionFeature,\n rowSortingFeature,\n SortingState,\n sortFn_alphanumeric,\n sortFn_alphanumericCaseSensitive,\n sortFn_basic,\n sortFn_datetime,\n sortFn_text,\n sortFn_textCaseSensitive,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport {\n Box,\n BoxProps,\n Center,\n Checkbox,\n DefaultMantineColor,\n Group,\n HoverCard,\n Loader,\n Table,\n TableProps,\n Text,\n UnstyledButton,\n} from \"@mantine/core\";\nimport { ArrowDown, ArrowUp, Info, Minus } from \"lucide-react\";\n\n// All built-in sort fns are registered so consumer columns can keep\n// using `sortFn: \"auto\"` (the default) or any built-in name.\nconst features = tableFeatures({\n rowSortingFeature,\n rowSelectionFeature,\n columnVisibilityFeature,\n sortedRowModel: createSortedRowModel(),\n sortFns: {\n alphanumeric: sortFn_alphanumeric,\n alphanumericCaseSensitive: sortFn_alphanumericCaseSensitive,\n basic: sortFn_basic,\n datetime: sortFn_datetime,\n text: sortFn_text,\n textCaseSensitive: sortFn_textCaseSensitive,\n },\n});\n\n/** The table features `DataTable` is built with.\n * Use as the `TFeatures` generic on `ColumnDef` / `Column` etc. */\nexport type DataTableFeatures = typeof features;\n\nfunction loadStoredSorting(tableKey: string): SortingState | null {\n try {\n const stored = localStorage.getItem(\"data-table-\" + tableKey);\n return stored ? (JSON.parse(stored) as SortingState) : null;\n } catch {\n return null;\n }\n}\n\nexport interface DataTableProps<TData extends RowData, TValue = unknown>\n extends BoxProps {\n /** Unique key given to table so sorting can be remembered on local storage */\n tableKey: string;\n columns: (ColumnDef<DataTableFeatures, TData, TValue> | false | undefined)[];\n data: TData[];\n loading?: boolean;\n onRowClick?: (row: TData) => void;\n /** Called when a row is right clicked. The consumer decides whether to\n * `preventDefault` the native context menu. */\n onRowContextMenu?: (row: TData, e: MouseEvent<HTMLTableRowElement>) => void;\n noResults?: ReactNode;\n defaultSort?: SortingState;\n sortDescFirst?: boolean;\n /** Sorting is handled externally (eg. server side).\n * The table still manages / persists the sorting state,\n * but does not apply it to the rows. */\n manualSorting?: boolean;\n /** Called with the sorting state whenever it changes.\n * Also called on mount with the initial state\n * (loaded from local storage when available). */\n onSortingStateChange?: (sorting: SortingState) => void;\n selectOptions?: {\n selectKey: (row: TData) => string;\n onSelect?: (selected: string[]) => void;\n state?: [RowSelectionState, Dispatch<SetStateAction<RowSelectionState>>];\n disableRow?: boolean | ((row: Row<DataTableFeatures, TData>) => boolean);\n color?: DefaultMantineColor;\n };\n caption?: string;\n tableProps?: TableProps;\n noBox?: boolean;\n noBorder?: boolean;\n}\n\nexport function DataTable<TData extends RowData, TValue>({\n tableKey,\n columns,\n data,\n loading,\n onRowClick,\n onRowContextMenu,\n noResults = <Text c=\"dimmed\">No results</Text>,\n sortDescFirst = false,\n defaultSort = [],\n manualSorting,\n onSortingStateChange,\n selectOptions,\n caption,\n tableProps,\n noBox,\n noBorder,\n mah = \"max(150px, calc(100vh - 320px))\",\n ...boxProps\n}: DataTableProps<TData, TValue>) {\n // Initialized synchronously from local storage so the first render\n // (and any server side sorted query) already uses the persisted sort,\n // instead of flashing through the unsorted state.\n const [sorting, setSorting] = useState<SortingState>(\n () => loadStoredSorting(tableKey) ?? defaultSort,\n );\n const [prevTableKey, setPrevTableKey] = useState(tableKey);\n if (prevTableKey !== tableKey) {\n setPrevTableKey(tableKey);\n setSorting(loadStoredSorting(tableKey) ?? defaultSort);\n }\n\n // intentionally not initialized to clear selected values on table mount\n // could add some prop for adding default selected state to preserve between mounts\n const _internalState = useState<RowSelectionState>({});\n const [rowSelection, setRowSelection] = selectOptions?.state\n ? selectOptions.state\n : _internalState;\n\n const table = useTable({\n features,\n data,\n columns: columns.filter((c) => c) as any,\n onSortingChange: setSorting,\n manualSorting,\n state: {\n sorting,\n rowSelection,\n },\n sortDescFirst,\n onRowSelectionChange: setRowSelection,\n getRowId: selectOptions?.selectKey,\n enableRowSelection: selectOptions?.disableRow,\n });\n\n useEffect(() => {\n localStorage.setItem(\"data-table-\" + tableKey, JSON.stringify(sorting));\n }, [tableKey, sorting]);\n\n // Layout effect so the parent receives the initial (persisted) sorting\n // before any of its own passive effects run, ie before react-query\n // subscribes a server side sorted query using the pre-sort key.\n useLayoutEffect(() => {\n onSortingStateChange?.(sorting);\n }, [sorting]);\n\n useEffect(() => {\n selectOptions?.onSelect?.(Object.keys(rowSelection));\n }, [rowSelection]);\n\n const rows = table.getRowModel().rows;\n\n const tableNode = (\n <Table\n borderColor=\"accent-border\"\n captionSide=\"top\"\n stickyHeader\n {...tableProps}\n >\n {caption ? <Table.Caption>{caption}</Table.Caption> : null}\n\n <Table.Thead>\n {table.getHeaderGroups().map((hg, i) => (\n <Table.Tr key={hg.id}>\n {i === 0 && selectOptions && (\n <Table.Th\n onClick={() =>\n selectOptions.disableRow !== true &&\n table.toggleAllRowsSelected()\n }\n style={{\n cursor: \"pointer\",\n borderColor: \"var(--mantine-color-accent-border-0)\",\n borderWidth: 0,\n borderRightWidth: 1,\n borderStyle: \"solid\",\n }}\n >\n <Checkbox\n color={selectOptions.color ?? \"Neutral\"}\n disabled={selectOptions.disableRow === true}\n checked={table.getIsAllRowsSelected()}\n indeterminate={\n // v9: getIsSomeRowsSelected is true even when all are selected\n table.getIsSomeRowsSelected() && !table.getIsAllRowsSelected()\n }\n />\n </Table.Th>\n )}\n {hg.headers.map((header, i) => {\n // const canSort = header.column.getCanSort();\n // const sortState = header.column.getIsSorted();\n return (\n <Table.Th\n key={header.id}\n px=\"md\"\n style={{\n cursor: \"pointer\",\n borderColor: \"var(--mantine-color-accent-border-0)\",\n borderWidth: 0,\n borderRightWidth: i < hg.headers.length - 1 ? 1 : 0,\n borderStyle: \"solid\",\n }}\n >\n {header.isPlaceholder ? null : (\n <Text fw={600} size=\"sm\" lineClamp={1}>\n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n </Text>\n )}\n </Table.Th>\n );\n })}\n </Table.Tr>\n ))}\n </Table.Thead>\n\n <Table.Tbody>\n {loading ? (\n <Table.Tr>\n <Table.Td\n colSpan={\n table.getAllLeafColumns().length + (selectOptions ? 1 : 0)\n }\n >\n <Group justify=\"center\" py=\"lg\">\n <Loader size=\"sm\" />\n </Group>\n </Table.Td>\n </Table.Tr>\n ) : rows.length === 0 ? (\n <Table.Tr>\n <Table.Td\n colSpan={\n table.getAllLeafColumns().length + (selectOptions ? 1 : 0)\n }\n >\n <Group justify=\"center\" py=\"lg\">\n {noResults}\n </Group>\n </Table.Td>\n </Table.Tr>\n ) : (\n rows.map((row) => (\n <Table.Tr\n key={row.id}\n onContextMenu={\n onRowContextMenu\n ? (e) => onRowContextMenu(row.original, e)\n : undefined\n }\n style={{\n cursor: onRowClick ? \"pointer\" : undefined,\n contentVisibility: \"auto\",\n containIntrinsicSize: \"auto 2em\",\n }}\n >\n {selectOptions && (\n <Table.Td onClick={() => row.toggleSelected()}>\n <Checkbox\n aria-label=\"Select row\"\n color={selectOptions.color ?? \"Neutral\"}\n disabled={!row.getCanSelect()}\n checked={row.getIsSelected()}\n />\n </Table.Td>\n )}\n {row.getVisibleCells().map((cell) => (\n <Table.Td\n key={cell.id}\n onClick={\n onRowClick ? () => onRowClick(row.original) : undefined\n }\n style={{ flexWrap: \"nowrap\", textWrap: \"nowrap\" }}\n >\n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n </Table.Td>\n ))}\n </Table.Tr>\n ))\n )}\n </Table.Tbody>\n </Table>\n );\n\n if (noBox) {\n return tableNode;\n } else {\n return (\n <Box\n p={noBorder ? undefined : \"lg\"}\n pt=\"0\"\n className={noBorder ? undefined : \"bordered-light\"}\n bdrs=\"md\"\n w=\"100%\"\n mah={mah}\n style={{ overflow: \"auto\" }}\n {...boxProps}\n >\n {tableNode}\n </Box>\n );\n }\n}\n\nexport const SortableHeader = <T extends RowData, V>({\n column,\n title,\n description,\n sortDescFirst,\n disabled,\n}: {\n column: Column<DataTableFeatures, T, V>;\n title: string;\n description?: ReactNode;\n sortDescFirst?: boolean;\n disabled?: boolean;\n}) => {\n if (disabled || !column.getCanSort()) {\n return (\n <Group justify=\"start\" gap=\"xs\" wrap=\"nowrap\" miw=\"120\" w=\"fit-content\">\n <Text fw={600} size=\"sm\" lineClamp={1}>\n {title}\n </Text>\n {description && (\n <HoverCard offset={10}>\n <HoverCard.Target>\n <Info size=\"1rem\" />\n </HoverCard.Target>\n <HoverCard.Dropdown>\n <Text>{description}</Text>\n </HoverCard.Dropdown>\n </HoverCard>\n )}\n </Group>\n );\n }\n return (\n <UnstyledButton\n onClick={column.getToggleSortingHandler()}\n style={{ width: \"100%\" }}\n >\n <Group justify=\"space-between\" gap=\"sm\" wrap=\"nowrap\">\n <Group justify=\"start\" gap=\"xs\" wrap=\"nowrap\" miw=\"120\" w=\"fit-content\">\n <Text fw={600} size=\"sm\" lineClamp={1}>\n {title}\n </Text>\n {description && (\n <HoverCard offset={10}>\n <HoverCard.Target>\n <Info size=\"1rem\" />\n </HoverCard.Target>\n <HoverCard.Dropdown>\n <Text>{description}</Text>\n </HoverCard.Dropdown>\n </HoverCard>\n )}\n </Group>\n <Center>\n <SortIcon\n state={column.getIsSorted()}\n sortDescFirst={sortDescFirst}\n />\n </Center>\n </Group>\n </UnstyledButton>\n );\n};\n\nfunction SortIcon({\n state,\n sortDescFirst,\n}: {\n state: false | \"asc\" | \"desc\";\n sortDescFirst?: boolean;\n}) {\n if (state === \"asc\")\n return sortDescFirst ? <ArrowUp size={14} /> : <ArrowDown size={14} />;\n if (state === \"desc\")\n return sortDescFirst ? <ArrowDown size={14} /> : <ArrowUp size={14} />;\n return <Minus size={14} />;\n}\n"],"mappings":"AAsHc,cA4EJ,YA5EI;AAtHd;AAAA,EAKE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EAGE;AAAA,EACA;AAAA,EACA;AAAA,EAIA;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EAEA;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,OACK;AACP,SAAS,WAAW,SAAS,MAAM,aAAa;AAIhD,MAAM,WAAW,cAAc;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA,gBAAgB,qBAAqB;AAAA,EACrC,SAAS;AAAA,IACP,cAAc;AAAA,IACd,2BAA2B;AAAA,IAC3B,OAAO;AAAA,IACP,UAAU;AAAA,IACV,MAAM;AAAA,IACN,mBAAmB;AAAA,EACrB;AACF,CAAC;AAMD,SAAS,kBAAkB,UAAuC;AAChE,MAAI;AACF,UAAM,SAAS,aAAa,QAAQ,gBAAgB,QAAQ;AAC5D,WAAO,SAAU,KAAK,MAAM,MAAM,IAAqB;AAAA,EACzD,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAqCO,SAAS,UAAyC;AAAA,EACvD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY,oBAAC,QAAK,GAAE,UAAS,wBAAU;AAAA,EACvC,gBAAgB;AAAA,EAChB,cAAc,CAAC;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,MAAM;AAAA,EACN,GAAG;AACL,GAAkC;AAIhC,QAAM,CAAC,SAAS,UAAU,IAAI;AAAA,IAC5B,MAAM,kBAAkB,QAAQ,KAAK;AAAA,EACvC;AACA,QAAM,CAAC,cAAc,eAAe,IAAI,SAAS,QAAQ;AACzD,MAAI,iBAAiB,UAAU;AAC7B,oBAAgB,QAAQ;AACxB,eAAW,kBAAkB,QAAQ,KAAK,WAAW;AAAA,EACvD;AAIA,QAAM,iBAAiB,SAA4B,CAAC,CAAC;AACrD,QAAM,CAAC,cAAc,eAAe,IAAI,eAAe,QACnD,cAAc,QACd;AAEJ,QAAM,QAAQ,SAAS;AAAA,IACrB;AAAA,IACA;AAAA,IACA,SAAS,QAAQ,OAAO,CAAC,MAAM,CAAC;AAAA,IAChC,iBAAiB;AAAA,IACjB;AAAA,IACA,OAAO;AAAA,MACL;AAAA,MACA;AAAA,IACF;AAAA,IACA;AAAA,IACA,sBAAsB;AAAA,IACtB,UAAU,eAAe;AAAA,IACzB,oBAAoB,eAAe;AAAA,EACrC,CAAC;AAED,YAAU,MAAM;AACd,iBAAa,QAAQ,gBAAgB,UAAU,KAAK,UAAU,OAAO,CAAC;AAAA,EACxE,GAAG,CAAC,UAAU,OAAO,CAAC;AAKtB,kBAAgB,MAAM;AACpB,2BAAuB,OAAO;AAAA,EAChC,GAAG,CAAC,OAAO,CAAC;AAEZ,YAAU,MAAM;AACd,mBAAe,WAAW,OAAO,KAAK,YAAY,CAAC;AAAA,EACrD,GAAG,CAAC,YAAY,CAAC;AAEjB,QAAM,OAAO,MAAM,YAAY,EAAE;AAEjC,QAAM,YACJ;AAAA,IAAC;AAAA;AAAA,MACC,aAAY;AAAA,MACZ,aAAY;AAAA,MACZ,cAAY;AAAA,MACX,GAAG;AAAA,MAEH;AAAA,kBAAU,oBAAC,MAAM,SAAN,EAAe,mBAAQ,IAAmB;AAAA,QAEtD,oBAAC,MAAM,OAAN,EACE,gBAAM,gBAAgB,EAAE,IAAI,CAAC,IAAI,MAChC,qBAAC,MAAM,IAAN,EACE;AAAA,gBAAM,KAAK,iBACV;AAAA,YAAC,MAAM;AAAA,YAAN;AAAA,cACC,SAAS,MACP,cAAc,eAAe,QAC7B,MAAM,sBAAsB;AAAA,cAE9B,OAAO;AAAA,gBACL,QAAQ;AAAA,gBACR,aAAa;AAAA,gBACb,aAAa;AAAA,gBACb,kBAAkB;AAAA,gBAClB,aAAa;AAAA,cACf;AAAA,cAEA;AAAA,gBAAC;AAAA;AAAA,kBACC,OAAO,cAAc,SAAS;AAAA,kBAC9B,UAAU,cAAc,eAAe;AAAA,kBACvC,SAAS,MAAM,qBAAqB;AAAA,kBACpC;AAAA;AAAA,oBAEE,MAAM,sBAAsB,KAAK,CAAC,MAAM,qBAAqB;AAAA;AAAA;AAAA,cAEjE;AAAA;AAAA,UACF;AAAA,UAED,GAAG,QAAQ,IAAI,CAAC,QAAQA,OAAM;AAG7B,mBACE;AAAA,cAAC,MAAM;AAAA,cAAN;AAAA,gBAEC,IAAG;AAAA,gBACH,OAAO;AAAA,kBACL,QAAQ;AAAA,kBACR,aAAa;AAAA,kBACb,aAAa;AAAA,kBACb,kBAAkBA,KAAI,GAAG,QAAQ,SAAS,IAAI,IAAI;AAAA,kBAClD,aAAa;AAAA,gBACf;AAAA,gBAEC,iBAAO,gBAAgB,OACtB,oBAAC,QAAK,IAAI,KAAK,MAAK,MAAK,WAAW,GACjC;AAAA,kBACC,OAAO,OAAO,UAAU;AAAA,kBACxB,OAAO,WAAW;AAAA,gBACpB,GACF;AAAA;AAAA,cAhBG,OAAO;AAAA,YAkBd;AAAA,UAEJ,CAAC;AAAA,aAnDY,GAAG,EAoDlB,CACD,GACH;AAAA,QAEA,oBAAC,MAAM,OAAN,EACE,oBACC,oBAAC,MAAM,IAAN,EACC;AAAA,UAAC,MAAM;AAAA,UAAN;AAAA,YACC,SACE,MAAM,kBAAkB,EAAE,UAAU,gBAAgB,IAAI;AAAA,YAG1D,8BAAC,SAAM,SAAQ,UAAS,IAAG,MACzB,8BAAC,UAAO,MAAK,MAAK,GACpB;AAAA;AAAA,QACF,GACF,IACE,KAAK,WAAW,IAClB,oBAAC,MAAM,IAAN,EACC;AAAA,UAAC,MAAM;AAAA,UAAN;AAAA,YACC,SACE,MAAM,kBAAkB,EAAE,UAAU,gBAAgB,IAAI;AAAA,YAG1D,8BAAC,SAAM,SAAQ,UAAS,IAAG,MACxB,qBACH;AAAA;AAAA,QACF,GACF,IAEA,KAAK,IAAI,CAAC,QACR;AAAA,UAAC,MAAM;AAAA,UAAN;AAAA,YAEC,eACE,mBACI,CAAC,MAAM,iBAAiB,IAAI,UAAU,CAAC,IACvC;AAAA,YAEN,OAAO;AAAA,cACL,QAAQ,aAAa,YAAY;AAAA,cACjC,mBAAmB;AAAA,cACnB,sBAAsB;AAAA,YACxB;AAAA,YAEC;AAAA,+BACC,oBAAC,MAAM,IAAN,EAAS,SAAS,MAAM,IAAI,eAAe,GAC1C;AAAA,gBAAC;AAAA;AAAA,kBACC,cAAW;AAAA,kBACX,OAAO,cAAc,SAAS;AAAA,kBAC9B,UAAU,CAAC,IAAI,aAAa;AAAA,kBAC5B,SAAS,IAAI,cAAc;AAAA;AAAA,cAC7B,GACF;AAAA,cAED,IAAI,gBAAgB,EAAE,IAAI,CAAC,SAC1B;AAAA,gBAAC,MAAM;AAAA,gBAAN;AAAA,kBAEC,SACE,aAAa,MAAM,WAAW,IAAI,QAAQ,IAAI;AAAA,kBAEhD,OAAO,EAAE,UAAU,UAAU,UAAU,SAAS;AAAA,kBAE/C,qBAAW,KAAK,OAAO,UAAU,MAAM,KAAK,WAAW,CAAC;AAAA;AAAA,gBANpD,KAAK;AAAA,cAOZ,CACD;AAAA;AAAA;AAAA,UAhCI,IAAI;AAAA,QAiCX,CACD,GAEL;AAAA;AAAA;AAAA,EACF;AAGF,MAAI,OAAO;AACT,WAAO;AAAA,EACT,OAAO;AACL,WACE;AAAA,MAAC;AAAA;AAAA,QACC,GAAG,WAAW,SAAY;AAAA,QAC1B,IAAG;AAAA,QACH,WAAW,WAAW,SAAY;AAAA,QAClC,MAAK;AAAA,QACL,GAAE;AAAA,QACF;AAAA,QACA,OAAO,EAAE,UAAU,OAAO;AAAA,QACzB,GAAG;AAAA,QAEH;AAAA;AAAA,IACH;AAAA,EAEJ;AACF;AAEO,MAAM,iBAAiB,CAAuB;AAAA,EACnD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAMM;AACJ,MAAI,YAAY,CAAC,OAAO,WAAW,GAAG;AACpC,WACE,qBAAC,SAAM,SAAQ,SAAQ,KAAI,MAAK,MAAK,UAAS,KAAI,OAAM,GAAE,eACxD;AAAA,0BAAC,QAAK,IAAI,KAAK,MAAK,MAAK,WAAW,GACjC,iBACH;AAAA,MACC,eACC,qBAAC,aAAU,QAAQ,IACjB;AAAA,4BAAC,UAAU,QAAV,EACC,8BAAC,QAAK,MAAK,QAAO,GACpB;AAAA,QACA,oBAAC,UAAU,UAAV,EACC,8BAAC,QAAM,uBAAY,GACrB;AAAA,SACF;AAAA,OAEJ;AAAA,EAEJ;AACA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,SAAS,OAAO,wBAAwB;AAAA,MACxC,OAAO,EAAE,OAAO,OAAO;AAAA,MAEvB,+BAAC,SAAM,SAAQ,iBAAgB,KAAI,MAAK,MAAK,UAC3C;AAAA,6BAAC,SAAM,SAAQ,SAAQ,KAAI,MAAK,MAAK,UAAS,KAAI,OAAM,GAAE,eACxD;AAAA,8BAAC,QAAK,IAAI,KAAK,MAAK,MAAK,WAAW,GACjC,iBACH;AAAA,UACC,eACC,qBAAC,aAAU,QAAQ,IACjB;AAAA,gCAAC,UAAU,QAAV,EACC,8BAAC,QAAK,MAAK,QAAO,GACpB;AAAA,YACA,oBAAC,UAAU,UAAV,EACC,8BAAC,QAAM,uBAAY,GACrB;AAAA,aACF;AAAA,WAEJ;AAAA,QACA,oBAAC,UACC;AAAA,UAAC;AAAA;AAAA,YACC,OAAO,OAAO,YAAY;AAAA,YAC1B;AAAA;AAAA,QACF,GACF;AAAA,SACF;AAAA;AAAA,EACF;AAEJ;AAEA,SAAS,SAAS;AAAA,EAChB;AAAA,EACA;AACF,GAGG;AACD,MAAI,UAAU;AACZ,WAAO,gBAAgB,oBAAC,WAAQ,MAAM,IAAI,IAAK,oBAAC,aAAU,MAAM,IAAI;AACtE,MAAI,UAAU;AACZ,WAAO,gBAAgB,oBAAC,aAAU,MAAM,IAAI,IAAK,oBAAC,WAAQ,MAAM,IAAI;AACtE,SAAO,oBAAC,SAAM,MAAM,IAAI;AAC1B;","names":["i"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mogh_ui",
3
- "version": "1.1.2",
3
+ "version": "1.1.4",
4
4
  "description": "Common UI components and styling used across Mogh apps.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",