@coveord/plasma-mantine 55.6.0 → 55.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/.turbo/turbo-build.log +3 -3
  2. package/.turbo/turbo-test.log +54 -52
  3. package/dist/.tsbuildinfo +1 -1
  4. package/dist/cjs/components/code-editor/CodeEditor.d.ts +7 -0
  5. package/dist/cjs/components/code-editor/CodeEditor.d.ts.map +1 -1
  6. package/dist/cjs/components/code-editor/CodeEditor.js +6 -3
  7. package/dist/cjs/components/code-editor/CodeEditor.js.map +1 -1
  8. package/dist/cjs/components/index.d.ts +1 -0
  9. package/dist/cjs/components/index.d.ts.map +1 -1
  10. package/dist/cjs/components/index.js +1 -0
  11. package/dist/cjs/components/index.js.map +1 -1
  12. package/dist/cjs/components/modal/Modal.d.ts +11 -0
  13. package/dist/cjs/components/modal/Modal.d.ts.map +1 -0
  14. package/dist/cjs/components/modal/Modal.js +32 -0
  15. package/dist/cjs/components/modal/Modal.js.map +1 -0
  16. package/dist/cjs/components/modal/Modal.module.css +9 -0
  17. package/dist/cjs/components/modal/ModalFooter.d.ts +20 -0
  18. package/dist/cjs/components/modal/ModalFooter.d.ts.map +1 -0
  19. package/dist/cjs/components/modal/ModalFooter.js +46 -0
  20. package/dist/cjs/components/modal/ModalFooter.js.map +1 -0
  21. package/dist/cjs/components/modal/index.d.ts +3 -0
  22. package/dist/cjs/components/modal/index.d.ts.map +1 -0
  23. package/dist/cjs/components/modal/index.js +9 -0
  24. package/dist/cjs/components/modal/index.js.map +1 -0
  25. package/dist/cjs/components/prompt/Prompt.d.ts +3 -3
  26. package/dist/cjs/components/prompt/Prompt.d.ts.map +1 -1
  27. package/dist/cjs/components/prompt/Prompt.js +14 -16
  28. package/dist/cjs/components/prompt/Prompt.js.map +1 -1
  29. package/dist/cjs/components/sticky-footer/StickyFooter.d.ts +2 -0
  30. package/dist/cjs/components/sticky-footer/StickyFooter.d.ts.map +1 -1
  31. package/dist/cjs/components/sticky-footer/StickyFooter.js.map +1 -1
  32. package/dist/cjs/components/table/use-url-synced-state.d.ts.map +1 -1
  33. package/dist/cjs/components/table/use-url-synced-state.js +29 -19
  34. package/dist/cjs/components/table/use-url-synced-state.js.map +1 -1
  35. package/dist/cjs/index.d.ts +1 -1
  36. package/dist/cjs/index.d.ts.map +1 -1
  37. package/dist/cjs/index.js +3 -0
  38. package/dist/cjs/index.js.map +1 -1
  39. package/dist/esm/components/code-editor/CodeEditor.d.ts +7 -0
  40. package/dist/esm/components/code-editor/CodeEditor.d.ts.map +1 -1
  41. package/dist/esm/components/code-editor/CodeEditor.js +4 -2
  42. package/dist/esm/components/code-editor/CodeEditor.js.map +1 -1
  43. package/dist/esm/components/index.d.ts +1 -0
  44. package/dist/esm/components/index.d.ts.map +1 -1
  45. package/dist/esm/components/index.js +1 -0
  46. package/dist/esm/components/index.js.map +1 -1
  47. package/dist/esm/components/modal/Modal.d.ts +11 -0
  48. package/dist/esm/components/modal/Modal.d.ts.map +1 -0
  49. package/dist/esm/components/modal/Modal.js +20 -0
  50. package/dist/esm/components/modal/Modal.js.map +1 -0
  51. package/dist/esm/components/modal/Modal.module.css +9 -0
  52. package/dist/esm/components/modal/ModalFooter.d.ts +20 -0
  53. package/dist/esm/components/modal/ModalFooter.d.ts.map +1 -0
  54. package/dist/esm/components/modal/ModalFooter.js +32 -0
  55. package/dist/esm/components/modal/ModalFooter.js.map +1 -0
  56. package/dist/esm/components/modal/index.d.ts +3 -0
  57. package/dist/esm/components/modal/index.d.ts.map +1 -0
  58. package/dist/esm/components/modal/index.js +4 -0
  59. package/dist/esm/components/modal/index.js.map +1 -0
  60. package/dist/esm/components/prompt/Prompt.d.ts +3 -3
  61. package/dist/esm/components/prompt/Prompt.d.ts.map +1 -1
  62. package/dist/esm/components/prompt/Prompt.js +9 -7
  63. package/dist/esm/components/prompt/Prompt.js.map +1 -1
  64. package/dist/esm/components/sticky-footer/StickyFooter.d.ts +2 -0
  65. package/dist/esm/components/sticky-footer/StickyFooter.d.ts.map +1 -1
  66. package/dist/esm/components/sticky-footer/StickyFooter.js.map +1 -1
  67. package/dist/esm/components/table/use-url-synced-state.d.ts.map +1 -1
  68. package/dist/esm/components/table/use-url-synced-state.js +26 -18
  69. package/dist/esm/components/table/use-url-synced-state.js.map +1 -1
  70. package/dist/esm/index.d.ts +1 -1
  71. package/dist/esm/index.d.ts.map +1 -1
  72. package/dist/esm/index.js +1 -1
  73. package/dist/esm/index.js.map +1 -1
  74. package/package.json +25 -25
  75. package/src/components/code-editor/CodeEditor.tsx +8 -1
  76. package/src/components/index.ts +1 -0
  77. package/src/components/modal/Modal.module.css +9 -0
  78. package/src/components/modal/Modal.tsx +33 -0
  79. package/src/components/modal/ModalFooter.tsx +47 -0
  80. package/src/components/modal/__tests__/Modal.spec.tsx +25 -0
  81. package/src/components/modal/__tests__/ModalFooter.spec.tsx +35 -0
  82. package/src/components/modal/index.ts +2 -0
  83. package/src/components/prompt/Prompt.tsx +9 -8
  84. package/src/components/sticky-footer/StickyFooter.tsx +2 -0
  85. package/src/components/table/__tests__/use-url-synced-state.unit.spec.ts +189 -138
  86. package/src/components/table/use-url-synced-state.ts +36 -18
  87. package/src/index.ts +2 -0
  88. package/dist/cjs/components/prompt/PromptFooter.d.ts +0 -6
  89. package/dist/cjs/components/prompt/PromptFooter.d.ts.map +0 -1
  90. package/dist/cjs/components/prompt/PromptFooter.js +0 -27
  91. package/dist/cjs/components/prompt/PromptFooter.js.map +0 -1
  92. package/dist/esm/components/prompt/PromptFooter.d.ts +0 -6
  93. package/dist/esm/components/prompt/PromptFooter.d.ts.map +0 -1
  94. package/dist/esm/components/prompt/PromptFooter.js +0 -9
  95. package/dist/esm/components/prompt/PromptFooter.js.map +0 -1
  96. package/src/components/prompt/PromptFooter.tsx +0 -10
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/components/prompt/Prompt.tsx"],"sourcesContent":["import {\n Box,\n createVarsResolver,\n factory,\n Factory,\n Image,\n Modal,\n ModalRootProps,\n ModalStylesNames,\n StylesApiProps,\n useProps,\n useStyles,\n} from '@mantine/core';\nimport {Children, ReactElement, ReactNode} from 'react';\nimport Critical from './icons/critical.svg';\nimport Info from './icons/info.svg';\nimport Success from './icons/success.svg';\nimport Warning from './icons/warning.svg';\nimport {PromptContextProvider} from './Prompt.context';\nimport classes from './Prompt.module.css';\nimport {PromptCancelButton, PromptCancelButtonStylesNamesVariant} from './PromptCancelButton';\nimport {PromptConfirmButton, PromptConfirmButtonStylesNamesVariant} from './PromptConfirmButton';\nimport {PromptFooter} from './PromptFooter';\n\nexport type PromptVariant = 'success' | 'warning' | 'critical' | 'info';\nexport type PromptVars = {root: '--prompt-icon-size'};\nexport type PromptStylesNames =\n | ModalStylesNames\n | 'icon'\n | PromptCancelButtonStylesNamesVariant\n | PromptConfirmButtonStylesNamesVariant;\n\nexport interface PromptProps\n extends StylesApiProps<PromptFactory>,\n Omit<ModalRootProps, 'classNames' | 'styles' | 'vars'> {\n /**\n * Controls prompt appearance\n *\n * @default \"info\"\n */\n variant?: PromptVariant;\n children: ReactNode;\n title: ReactNode;\n icon?: ReactNode;\n}\n\nexport type PromptFactory = Factory<{\n props: PromptProps;\n ref: HTMLDivElement;\n vars: PromptVars;\n variant: PromptVariant;\n stylesNames: PromptStylesNames;\n staticComponents: {\n CancelButton: typeof PromptCancelButton;\n ConfirmButton: typeof PromptConfirmButton;\n Footer: typeof PromptFooter;\n };\n}>;\n\nconst PROMPT_VARIANT_ICONS_SRC: Record<PromptVariant, string> = {\n success: Success,\n warning: Warning,\n critical: Critical,\n info: Info,\n};\n\nconst defaultProps: Partial<PromptProps> = {\n variant: 'info',\n centered: true,\n};\n\nconst varsResolver = createVarsResolver<PromptFactory>((_theme, {icon}) => ({\n root: {\n '--prompt-icon-size': icon ? undefined : '88px',\n },\n}));\n\nexport const Prompt = factory<PromptFactory>((_props, ref) => {\n const props = useProps('Prompt', defaultProps, _props);\n const {variant, title, icon, children, className, classNames, style, styles, unstyled, vars, ...others} = props;\n const getStyles = useStyles<PromptFactory>({\n name: 'Prompt',\n props,\n classes,\n className,\n style,\n classNames,\n styles,\n unstyled,\n vars,\n varsResolver,\n });\n const stylesApiProps = {classNames, styles};\n\n const convertedChildren = Children.toArray(children) as ReactElement[];\n\n const otherChildren = convertedChildren.filter((child) => child.type !== PromptFooter);\n const footer = convertedChildren.find((child) => child.type === PromptFooter);\n\n return (\n <PromptContextProvider value={{variant, getStyles}}>\n <Modal.Root ref={ref} variant=\"prompt\" size=\"sm\" {...others} {...getStyles('root')}>\n <Modal.Overlay {...getStyles('overlay', stylesApiProps)} />\n <Modal.Content {...getStyles('content', stylesApiProps)}>\n <Modal.Header {...getStyles('header', stylesApiProps)}>\n {icon || icon === null ? (\n icon\n ) : (\n <Image\n alt=\"\"\n role=\"presentation\"\n {...getStyles('icon', stylesApiProps)}\n src={PROMPT_VARIANT_ICONS_SRC[variant]}\n />\n )}\n <Modal.Title {...getStyles('title', stylesApiProps)}>{title}</Modal.Title>\n <Modal.CloseButton {...getStyles('close', stylesApiProps)} />\n </Modal.Header>\n <Modal.Body {...getStyles('body', stylesApiProps)}>\n <Box {...getStyles('inner', stylesApiProps)}>{otherChildren}</Box>\n </Modal.Body>\n {footer}\n </Modal.Content>\n </Modal.Root>\n </PromptContextProvider>\n );\n});\n\nPrompt.CancelButton = PromptCancelButton;\nPrompt.ConfirmButton = PromptConfirmButton;\nPrompt.Footer = PromptFooter;\n"],"names":["Box","createVarsResolver","factory","Image","Modal","useProps","useStyles","Children","Critical","Info","Success","Warning","PromptContextProvider","classes","PromptCancelButton","PromptConfirmButton","PromptFooter","PROMPT_VARIANT_ICONS_SRC","success","warning","critical","info","defaultProps","variant","centered","varsResolver","_theme","icon","root","undefined","Prompt","_props","ref","props","title","children","className","classNames","style","styles","unstyled","vars","others","getStyles","name","stylesApiProps","convertedChildren","toArray","otherChildren","filter","child","type","footer","find","value","Root","size","Overlay","Content","Header","alt","role","src","Title","CloseButton","Body","CancelButton","ConfirmButton","Footer"],"mappings":";AAAA,SACIA,GAAG,EACHC,kBAAkB,EAClBC,OAAO,EAEPC,KAAK,EACLC,KAAK,EAILC,QAAQ,EACRC,SAAS,QACN,gBAAgB;AACvB,SAAQC,QAAQ,QAAgC,QAAQ;AACxD,OAAOC,cAAc,uBAAuB;AAC5C,OAAOC,UAAU,mBAAmB;AACpC,OAAOC,aAAa,sBAAsB;AAC1C,OAAOC,aAAa,sBAAsB;AAC1C,SAAQC,qBAAqB,QAAO,mBAAmB;AACvD,OAAOC,aAAa,sBAAsB;AAC1C,SAAQC,kBAAkB,QAA6C,uBAAuB;AAC9F,SAAQC,mBAAmB,QAA8C,wBAAwB;AACjG,SAAQC,YAAY,QAAO,iBAAiB;AAqC5C,MAAMC,2BAA0D;IAC5DC,SAASR;IACTS,SAASR;IACTS,UAAUZ;IACVa,MAAMZ;AACV;AAEA,MAAMa,eAAqC;IACvCC,SAAS;IACTC,UAAU;AACd;AAEA,MAAMC,eAAexB,mBAAkC,CAACyB,QAAQ,EAACC,IAAI,EAAC,GAAM,CAAA;QACxEC,MAAM;YACF,sBAAsBD,OAAOE,YAAY;QAC7C;IACJ,CAAA;AAEA,OAAO,MAAMC,SAAS5B,QAAuB,CAAC6B,QAAQC;IAClD,MAAMC,QAAQ5B,SAAS,UAAUiB,cAAcS;IAC/C,MAAM,EAACR,OAAO,EAAEW,KAAK,EAAEP,IAAI,EAAEQ,QAAQ,EAAEC,SAAS,EAAEC,UAAU,EAAEC,KAAK,EAAEC,MAAM,EAAEC,QAAQ,EAAEC,IAAI,EAAE,GAAGC,QAAO,GAAGT;IAC1G,MAAMU,YAAYrC,UAAyB;QACvCsC,MAAM;QACNX;QACApB;QACAuB;QACAE;QACAD;QACAE;QACAC;QACAC;QACAhB;IACJ;IACA,MAAMoB,iBAAiB;QAACR;QAAYE;IAAM;IAE1C,MAAMO,oBAAoBvC,SAASwC,OAAO,CAACZ;IAE3C,MAAMa,gBAAgBF,kBAAkBG,MAAM,CAAC,CAACC,QAAUA,MAAMC,IAAI,KAAKnC;IACzE,MAAMoC,SAASN,kBAAkBO,IAAI,CAAC,CAACH,QAAUA,MAAMC,IAAI,KAAKnC;IAEhE,qBACI,KAACJ;QAAsB0C,OAAO;YAAC/B;YAASoB;QAAS;kBAC7C,cAAA,MAACvC,MAAMmD,IAAI;YAACvB,KAAKA;YAAKT,SAAQ;YAASiC,MAAK;YAAM,GAAGd,MAAM;YAAG,GAAGC,UAAU,OAAO;;8BAC9E,KAACvC,MAAMqD,OAAO;oBAAE,GAAGd,UAAU,WAAWE,eAAe;;8BACvD,MAACzC,MAAMsD,OAAO;oBAAE,GAAGf,UAAU,WAAWE,eAAe;;sCACnD,MAACzC,MAAMuD,MAAM;4BAAE,GAAGhB,UAAU,UAAUE,eAAe;;gCAChDlB,QAAQA,SAAS,OACdA,qBAEA,KAACxB;oCACGyD,KAAI;oCACJC,MAAK;oCACJ,GAAGlB,UAAU,QAAQE,eAAe;oCACrCiB,KAAK7C,wBAAwB,CAACM,QAAQ;;8CAG9C,KAACnB,MAAM2D,KAAK;oCAAE,GAAGpB,UAAU,SAASE,eAAe;8CAAGX;;8CACtD,KAAC9B,MAAM4D,WAAW;oCAAE,GAAGrB,UAAU,SAASE,eAAe;;;;sCAE7D,KAACzC,MAAM6D,IAAI;4BAAE,GAAGtB,UAAU,QAAQE,eAAe;sCAC7C,cAAA,KAAC7C;gCAAK,GAAG2C,UAAU,SAASE,eAAe;0CAAGG;;;wBAEjDI;;;;;;AAKrB,GAAG;AAEHtB,OAAOoC,YAAY,GAAGpD;AACtBgB,OAAOqC,aAAa,GAAGpD;AACvBe,OAAOsC,MAAM,GAAGpD"}
1
+ {"version":3,"sources":["../../../../src/components/prompt/Prompt.tsx"],"sourcesContent":["import {\n Box,\n createVarsResolver,\n factory,\n Factory,\n Image,\n ModalRootProps,\n ModalStylesNames,\n StylesApiProps,\n useProps,\n useStyles,\n} from '@mantine/core';\nimport {Children, ReactElement, ReactNode} from 'react';\nimport {Modal} from '../modal';\nimport Critical from './icons/critical.svg';\nimport Info from './icons/info.svg';\nimport Success from './icons/success.svg';\nimport Warning from './icons/warning.svg';\nimport {PromptContextProvider} from './Prompt.context';\nimport classes from './Prompt.module.css';\nimport {PromptCancelButton, PromptCancelButtonStylesNamesVariant} from './PromptCancelButton';\nimport {PromptConfirmButton, PromptConfirmButtonStylesNamesVariant} from './PromptConfirmButton';\n\nexport type PromptVariant = 'success' | 'warning' | 'critical' | 'info';\nexport type PromptVars = {root: '--prompt-icon-size'};\nexport type PromptStylesNames =\n | ModalStylesNames\n | 'icon'\n | PromptCancelButtonStylesNamesVariant\n | PromptConfirmButtonStylesNamesVariant;\n\nexport interface PromptProps\n extends StylesApiProps<PromptFactory>,\n Omit<ModalRootProps, 'classNames' | 'styles' | 'vars'> {\n /**\n * Controls prompt appearance\n *\n * @default \"info\"\n */\n variant?: PromptVariant;\n children: ReactNode;\n title: ReactNode;\n icon?: ReactNode;\n}\n\nexport type PromptFactory = Factory<{\n props: PromptProps;\n ref: HTMLDivElement;\n vars: PromptVars;\n variant: PromptVariant;\n stylesNames: PromptStylesNames;\n staticComponents: {\n CancelButton: typeof PromptCancelButton;\n ConfirmButton: typeof PromptConfirmButton;\n Footer: typeof Modal.Footer;\n };\n}>;\n\nconst PROMPT_VARIANT_ICONS_SRC: Record<PromptVariant, string> = {\n success: Success,\n warning: Warning,\n critical: Critical,\n info: Info,\n};\n\nconst defaultProps: Partial<PromptProps> = {\n variant: 'info',\n centered: true,\n};\n\nconst varsResolver = createVarsResolver<PromptFactory>((_theme, {icon}) => ({\n root: {\n '--prompt-icon-size': icon ? undefined : '88px',\n },\n}));\n\nexport const Prompt = factory<PromptFactory>((_props, ref) => {\n const props = useProps('Prompt', defaultProps, _props);\n const {variant, title, icon, children, className, classNames, style, styles, unstyled, vars, ...others} = props;\n const getStyles = useStyles<PromptFactory>({\n name: 'Prompt',\n props,\n classes,\n className,\n style,\n classNames,\n styles,\n unstyled,\n vars,\n varsResolver,\n });\n const stylesApiProps = {classNames, styles};\n\n const footers: ReactElement[] = [];\n const otherChildren: ReactElement[] = [];\n\n Children.forEach(children, (child: ReactElement) => {\n (child.type === Modal.Footer ? footers : otherChildren).push(child);\n });\n\n return (\n <PromptContextProvider value={{variant, getStyles}}>\n <Modal.Root ref={ref} variant=\"prompt\" size=\"sm\" {...others} {...getStyles('root')}>\n <Modal.Overlay {...getStyles('overlay', stylesApiProps)} />\n <Modal.Content {...getStyles('content', stylesApiProps)}>\n <Modal.Header {...getStyles('header', stylesApiProps)}>\n {icon || icon === null ? (\n icon\n ) : (\n <Image\n alt=\"\"\n role=\"presentation\"\n {...getStyles('icon', stylesApiProps)}\n src={PROMPT_VARIANT_ICONS_SRC[variant]}\n />\n )}\n <Modal.Title {...getStyles('title', stylesApiProps)}>{title}</Modal.Title>\n <Modal.CloseButton {...getStyles('close', stylesApiProps)} />\n </Modal.Header>\n <Modal.Body {...getStyles('body', stylesApiProps)}>\n <Box {...getStyles('inner', stylesApiProps)}>{otherChildren}</Box>\n </Modal.Body>\n {footers}\n </Modal.Content>\n </Modal.Root>\n </PromptContextProvider>\n );\n});\n\nPrompt.CancelButton = PromptCancelButton;\nPrompt.ConfirmButton = PromptConfirmButton;\nPrompt.Footer = Modal.Footer;\n"],"names":["Box","createVarsResolver","factory","Image","useProps","useStyles","Children","Modal","Critical","Info","Success","Warning","PromptContextProvider","classes","PromptCancelButton","PromptConfirmButton","PROMPT_VARIANT_ICONS_SRC","success","warning","critical","info","defaultProps","variant","centered","varsResolver","_theme","icon","root","undefined","Prompt","_props","ref","props","title","children","className","classNames","style","styles","unstyled","vars","others","getStyles","name","stylesApiProps","footers","otherChildren","forEach","child","type","Footer","push","value","Root","size","Overlay","Content","Header","alt","role","src","Title","CloseButton","Body","CancelButton","ConfirmButton"],"mappings":";AAAA,SACIA,GAAG,EACHC,kBAAkB,EAClBC,OAAO,EAEPC,KAAK,EAILC,QAAQ,EACRC,SAAS,QACN,gBAAgB;AACvB,SAAQC,QAAQ,QAAgC,QAAQ;AACxD,SAAQC,KAAK,QAAO,WAAW;AAC/B,OAAOC,cAAc,uBAAuB;AAC5C,OAAOC,UAAU,mBAAmB;AACpC,OAAOC,aAAa,sBAAsB;AAC1C,OAAOC,aAAa,sBAAsB;AAC1C,SAAQC,qBAAqB,QAAO,mBAAmB;AACvD,OAAOC,aAAa,sBAAsB;AAC1C,SAAQC,kBAAkB,QAA6C,uBAAuB;AAC9F,SAAQC,mBAAmB,QAA8C,wBAAwB;AAqCjG,MAAMC,2BAA0D;IAC5DC,SAASP;IACTQ,SAASP;IACTQ,UAAUX;IACVY,MAAMX;AACV;AAEA,MAAMY,eAAqC;IACvCC,SAAS;IACTC,UAAU;AACd;AAEA,MAAMC,eAAevB,mBAAkC,CAACwB,QAAQ,EAACC,IAAI,EAAC,GAAM,CAAA;QACxEC,MAAM;YACF,sBAAsBD,OAAOE,YAAY;QAC7C;IACJ,CAAA;AAEA,OAAO,MAAMC,SAAS3B,QAAuB,CAAC4B,QAAQC;IAClD,MAAMC,QAAQ5B,SAAS,UAAUiB,cAAcS;IAC/C,MAAM,EAACR,OAAO,EAAEW,KAAK,EAAEP,IAAI,EAAEQ,QAAQ,EAAEC,SAAS,EAAEC,UAAU,EAAEC,KAAK,EAAEC,MAAM,EAAEC,QAAQ,EAAEC,IAAI,EAAE,GAAGC,QAAO,GAAGT;IAC1G,MAAMU,YAAYrC,UAAyB;QACvCsC,MAAM;QACNX;QACAnB;QACAsB;QACAE;QACAD;QACAE;QACAC;QACAC;QACAhB;IACJ;IACA,MAAMoB,iBAAiB;QAACR;QAAYE;IAAM;IAE1C,MAAMO,UAA0B,EAAE;IAClC,MAAMC,gBAAgC,EAAE;IAExCxC,SAASyC,OAAO,CAACb,UAAU,CAACc;QACvBA,CAAAA,MAAMC,IAAI,KAAK1C,MAAM2C,MAAM,GAAGL,UAAUC,aAAY,EAAGK,IAAI,CAACH;IACjE;IAEA,qBACI,KAACpC;QAAsBwC,OAAO;YAAC9B;YAASoB;QAAS;kBAC7C,cAAA,MAACnC,MAAM8C,IAAI;YAACtB,KAAKA;YAAKT,SAAQ;YAASgC,MAAK;YAAM,GAAGb,MAAM;YAAG,GAAGC,UAAU,OAAO;;8BAC9E,KAACnC,MAAMgD,OAAO;oBAAE,GAAGb,UAAU,WAAWE,eAAe;;8BACvD,MAACrC,MAAMiD,OAAO;oBAAE,GAAGd,UAAU,WAAWE,eAAe;;sCACnD,MAACrC,MAAMkD,MAAM;4BAAE,GAAGf,UAAU,UAAUE,eAAe;;gCAChDlB,QAAQA,SAAS,OACdA,qBAEA,KAACvB;oCACGuD,KAAI;oCACJC,MAAK;oCACJ,GAAGjB,UAAU,QAAQE,eAAe;oCACrCgB,KAAK5C,wBAAwB,CAACM,QAAQ;;8CAG9C,KAACf,MAAMsD,KAAK;oCAAE,GAAGnB,UAAU,SAASE,eAAe;8CAAGX;;8CACtD,KAAC1B,MAAMuD,WAAW;oCAAE,GAAGpB,UAAU,SAASE,eAAe;;;;sCAE7D,KAACrC,MAAMwD,IAAI;4BAAE,GAAGrB,UAAU,QAAQE,eAAe;sCAC7C,cAAA,KAAC5C;gCAAK,GAAG0C,UAAU,SAASE,eAAe;0CAAGE;;;wBAEjDD;;;;;;AAKrB,GAAG;AAEHhB,OAAOmC,YAAY,GAAGlD;AACtBe,OAAOoC,aAAa,GAAGlD;AACvBc,OAAOqB,MAAM,GAAG3C,MAAM2C,MAAM"}
@@ -14,6 +14,8 @@ export interface StickyFooterProps extends Omit<GroupProps, 'classNames' | 'styl
14
14
  *
15
15
  * The 'modal-footer' removes the modal's default padding so that the footer properly hugs the bottom of the modal.
16
16
  * It also adds a border on top of the footer.
17
+ *
18
+ * @deprecated Use Modal.Footer from @coveord/plasma-mantine/Modal for modal footers. For other cases, the 'default' variant should suffice.
17
19
  */
18
20
  variant?: 'default' | 'modal-footer';
19
21
  }
@@ -1 +1 @@
1
- {"version":3,"file":"StickyFooter.d.ts","sourceRoot":"","sources":["../../../../src/components/sticky-footer/StickyFooter.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,EAAS,UAAU,EAAE,cAAc,EAA+B,MAAM,eAAe,CAAC;AAEvG,OAAO,EAAC,SAAS,EAAC,MAAM,OAAO,CAAC;AAGhC,MAAM,WAAW,iBACb,SAAQ,IAAI,CAAC,UAAU,EAAE,YAAY,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC,EAClE,cAAc,CAAC,mBAAmB,CAAC;IACvC;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,SAAS,GAAG,cAAc,CAAC;CACxC;AAED,MAAM,MAAM,uBAAuB,GAAG,MAAM,CAAC;AAE7C,MAAM,MAAM,mBAAmB,GAAG,OAAO,CAAC;IACtC,KAAK,EAAE,iBAAiB,CAAC;IACzB,GAAG,EAAE,cAAc,CAAC;IACpB,WAAW,EAAE,uBAAuB,CAAC;CACxC,CAAC,CAAC;AAOH,eAAO,MAAM,YAAY;WAVd,iBAAiB;SACnB,cAAc;iBACN,uBAAuB;EAoCtC,CAAC"}
1
+ {"version":3,"file":"StickyFooter.d.ts","sourceRoot":"","sources":["../../../../src/components/sticky-footer/StickyFooter.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,EAAS,UAAU,EAAE,cAAc,EAA+B,MAAM,eAAe,CAAC;AAEvG,OAAO,EAAC,SAAS,EAAC,MAAM,OAAO,CAAC;AAGhC,MAAM,WAAW,iBACb,SAAQ,IAAI,CAAC,UAAU,EAAE,YAAY,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC,EAClE,cAAc,CAAC,mBAAmB,CAAC;IACvC;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,SAAS,GAAG,cAAc,CAAC;CACxC;AAED,MAAM,MAAM,uBAAuB,GAAG,MAAM,CAAC;AAE7C,MAAM,MAAM,mBAAmB,GAAG,OAAO,CAAC;IACtC,KAAK,EAAE,iBAAiB,CAAC;IACzB,GAAG,EAAE,cAAc,CAAC;IACpB,WAAW,EAAE,uBAAuB,CAAC;CACxC,CAAC,CAAC;AAOH,eAAO,MAAM,YAAY;WAVd,iBAAiB;SACnB,cAAc;iBACN,uBAAuB;EAoCtC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/components/sticky-footer/StickyFooter.tsx"],"sourcesContent":["import {Factory, Group, GroupProps, StylesApiProps, factory, useProps, useStyles} from '@mantine/core';\nimport clsx from 'clsx';\nimport {ReactNode} from 'react';\nimport classes from './StickyFooter.module.css';\n\nexport interface StickyFooterProps\n extends Omit<GroupProps, 'classNames' | 'styles' | 'vars' | 'variant'>,\n StylesApiProps<StickyFooterFactory> {\n /**\n * Whether a border is render on top of the footer\n */\n borderTop?: boolean;\n /**\n * Footer's children, usually buttons\n */\n children?: ReactNode;\n /**\n * Use variant 'modal-footer' when rendering the `StickyFooter` inside `Modal`.\n *\n * The 'modal-footer' removes the modal's default padding so that the footer properly hugs the bottom of the modal.\n * It also adds a border on top of the footer.\n */\n variant?: 'default' | 'modal-footer';\n}\n\nexport type StickyFooterStylesNames = 'root';\n\nexport type StickyFooterFactory = Factory<{\n props: StickyFooterProps;\n ref: HTMLDivElement;\n stylesNames: StickyFooterStylesNames;\n}>;\n\nconst defaultProps: Partial<StickyFooterProps> = {\n gap: 'sm',\n justify: 'flex-end',\n};\n\nexport const StickyFooter = factory<StickyFooterFactory>((props, ref) => {\n const {borderTop, justify, gap, children, className, classNames, style, styles, unstyled, vars, ...others} =\n useProps('StickyFooter', defaultProps, props);\n const getStyles = useStyles<StickyFooterFactory>({\n name: 'StickyFooter',\n classes,\n props,\n className,\n style,\n classNames,\n styles,\n unstyled,\n });\n\n const css = getStyles('root');\n\n return (\n <Group\n justify={justify}\n gap={gap}\n className={clsx(css.className, {[classes.border]: !!borderTop})}\n style={css.style}\n ref={ref}\n {...others}\n >\n {children}\n </Group>\n );\n});\n"],"names":["Group","factory","useProps","useStyles","clsx","classes","defaultProps","gap","justify","StickyFooter","props","ref","borderTop","children","className","classNames","style","styles","unstyled","vars","others","getStyles","name","css","border"],"mappings":";AAAA,SAAiBA,KAAK,EAA8BC,OAAO,EAAEC,QAAQ,EAAEC,SAAS,QAAO,gBAAgB;AACvG,OAAOC,UAAU,OAAO;AAExB,OAAOC,aAAa,4BAA4B;AA8BhD,MAAMC,eAA2C;IAC7CC,KAAK;IACLC,SAAS;AACb;AAEA,OAAO,MAAMC,eAAeR,QAA6B,CAACS,OAAOC;IAC7D,MAAM,EAACC,SAAS,EAAEJ,OAAO,EAAED,GAAG,EAAEM,QAAQ,EAAEC,SAAS,EAAEC,UAAU,EAAEC,KAAK,EAAEC,MAAM,EAAEC,QAAQ,EAAEC,IAAI,EAAE,GAAGC,QAAO,GACtGlB,SAAS,gBAAgBI,cAAcI;IAC3C,MAAMW,YAAYlB,UAA+B;QAC7CmB,MAAM;QACNjB;QACAK;QACAI;QACAE;QACAD;QACAE;QACAC;IACJ;IAEA,MAAMK,MAAMF,UAAU;IAEtB,qBACI,KAACrB;QACGQ,SAASA;QACTD,KAAKA;QACLO,WAAWV,KAAKmB,IAAIT,SAAS,EAAE;YAAC,CAACT,QAAQmB,MAAM,CAAC,EAAE,CAAC,CAACZ;QAAS;QAC7DI,OAAOO,IAAIP,KAAK;QAChBL,KAAKA;QACJ,GAAGS,MAAM;kBAETP;;AAGb,GAAG"}
1
+ {"version":3,"sources":["../../../../src/components/sticky-footer/StickyFooter.tsx"],"sourcesContent":["import {Factory, Group, GroupProps, StylesApiProps, factory, useProps, useStyles} from '@mantine/core';\nimport clsx from 'clsx';\nimport {ReactNode} from 'react';\nimport classes from './StickyFooter.module.css';\n\nexport interface StickyFooterProps\n extends Omit<GroupProps, 'classNames' | 'styles' | 'vars' | 'variant'>,\n StylesApiProps<StickyFooterFactory> {\n /**\n * Whether a border is render on top of the footer\n */\n borderTop?: boolean;\n /**\n * Footer's children, usually buttons\n */\n children?: ReactNode;\n /**\n * Use variant 'modal-footer' when rendering the `StickyFooter` inside `Modal`.\n *\n * The 'modal-footer' removes the modal's default padding so that the footer properly hugs the bottom of the modal.\n * It also adds a border on top of the footer.\n *\n * @deprecated Use Modal.Footer from @coveord/plasma-mantine/Modal for modal footers. For other cases, the 'default' variant should suffice.\n */\n variant?: 'default' | 'modal-footer';\n}\n\nexport type StickyFooterStylesNames = 'root';\n\nexport type StickyFooterFactory = Factory<{\n props: StickyFooterProps;\n ref: HTMLDivElement;\n stylesNames: StickyFooterStylesNames;\n}>;\n\nconst defaultProps: Partial<StickyFooterProps> = {\n gap: 'sm',\n justify: 'flex-end',\n};\n\nexport const StickyFooter = factory<StickyFooterFactory>((props, ref) => {\n const {borderTop, justify, gap, children, className, classNames, style, styles, unstyled, vars, ...others} =\n useProps('StickyFooter', defaultProps, props);\n const getStyles = useStyles<StickyFooterFactory>({\n name: 'StickyFooter',\n classes,\n props,\n className,\n style,\n classNames,\n styles,\n unstyled,\n });\n\n const css = getStyles('root');\n\n return (\n <Group\n justify={justify}\n gap={gap}\n className={clsx(css.className, {[classes.border]: !!borderTop})}\n style={css.style}\n ref={ref}\n {...others}\n >\n {children}\n </Group>\n );\n});\n"],"names":["Group","factory","useProps","useStyles","clsx","classes","defaultProps","gap","justify","StickyFooter","props","ref","borderTop","children","className","classNames","style","styles","unstyled","vars","others","getStyles","name","css","border"],"mappings":";AAAA,SAAiBA,KAAK,EAA8BC,OAAO,EAAEC,QAAQ,EAAEC,SAAS,QAAO,gBAAgB;AACvG,OAAOC,UAAU,OAAO;AAExB,OAAOC,aAAa,4BAA4B;AAgChD,MAAMC,eAA2C;IAC7CC,KAAK;IACLC,SAAS;AACb;AAEA,OAAO,MAAMC,eAAeR,QAA6B,CAACS,OAAOC;IAC7D,MAAM,EAACC,SAAS,EAAEJ,OAAO,EAAED,GAAG,EAAEM,QAAQ,EAAEC,SAAS,EAAEC,UAAU,EAAEC,KAAK,EAAEC,MAAM,EAAEC,QAAQ,EAAEC,IAAI,EAAE,GAAGC,QAAO,GACtGlB,SAAS,gBAAgBI,cAAcI;IAC3C,MAAMW,YAAYlB,UAA+B;QAC7CmB,MAAM;QACNjB;QACAK;QACAI;QACAE;QACAD;QACAE;QACAC;IACJ;IAEA,MAAMK,MAAMF,UAAU;IAEtB,qBACI,KAACrB;QACGQ,SAASA;QACTD,KAAKA;QACLO,WAAWV,KAAKmB,IAAIT,SAAS,EAAE;YAAC,CAACT,QAAQmB,MAAM,CAAC,EAAE,CAAC,CAACZ;QAAS;QAC7DI,OAAOO,IAAIP,KAAK;QAChBL,KAAKA;QACJ,GAAGS,MAAM;kBAETP;;AAGb,GAAG"}
@@ -1 +1 @@
1
- {"version":3,"file":"use-url-synced-state.d.ts","sourceRoot":"","sources":["../../../../src/components/table/use-url-synced-state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAE,cAAc,EAAoB,MAAM,OAAO,CAAC;AAElE;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;AAyC7E,MAAM,WAAW,wBAAwB,CAAC,CAAC;IACvC;;;;OAIG;IACH,YAAY,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IAC5B;;;;;;;;;OASG;IACH,UAAU,EAAE,CAAC,UAAU,EAAE,CAAC,KAAK,QAAQ,CAAC,gBAAgB,CAAC,CAAC;IAC1D;;;;;;;;OAQG;IACH,YAAY,EAAE,CAAC,MAAM,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC,KAAK,CAAC,CAAC;IAC9D;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;CAClB;AAKD,eAAO,MAAM,iBAAiB,GAAI,CAAC,WAAW,wBAAwB,CAAC,CAAC,CAAC,8CA+CxE,CAAC"}
1
+ {"version":3,"file":"use-url-synced-state.d.ts","sourceRoot":"","sources":["../../../../src/components/table/use-url-synced-state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAE,cAAc,EAAoB,MAAM,OAAO,CAAC;AAElE;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;AAuD7E,MAAM,WAAW,wBAAwB,CAAC,CAAC;IACvC;;;;OAIG;IACH,YAAY,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IAC5B;;;;;;;;;OASG;IACH,UAAU,EAAE,CAAC,UAAU,EAAE,CAAC,KAAK,QAAQ,CAAC,gBAAgB,CAAC,CAAC;IAC1D;;;;;;;;OAQG;IACH,YAAY,EAAE,CAAC,MAAM,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC,KAAK,CAAC,CAAC;IAC9D;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;CAClB;AAKD,eAAO,MAAM,iBAAiB,GAAI,CAAC,WAAW,wBAAwB,CAAC,CAAC,CAAC,8CAmDxE,CAAC"}
@@ -1,20 +1,25 @@
1
1
  import { useMemo, useState } from 'react';
2
+ const slice = Function.prototype.call.bind(Array.prototype.slice);
2
3
  /**
3
- * Get the index of the ? in a URL that denotes the start of the "search".
4
- * Performs a nested search for '#/', to detect hash router urls and take the params of the hash in that case.
4
+ * Split a url into its parts.
5
5
  *
6
- * @param url The URL to search.
7
- * @returns The location of the question mark, or `-1` if not found.
8
- */ const indexOfSearch = (url)=>url.indexOf('?', url.indexOf('#/') + 1);
6
+ * @param href The url to extract the parts from.
7
+ * @returns The separate parts, all are an empty string if not present.
8
+ */ const extractParts = (href)=>slice(/^([^?#]*)(\?[^#]*|)(#[^?]*|)(\?.*|)$/.exec(href ?? ''), 1, 5);
9
+ /**
10
+ * The index of the search parameter to use, e.g. hashSearch for hash routes (hash starts with '#/').
11
+ *
12
+ * @param parts: The url parts, as returned by `extractParts`.
13
+ * @returns The index of the search parameter to use (1 or 3).
14
+ */ const searchIndex = (parts)=>/^#\//.test(parts[2]) ? 3 : 1;
9
15
  /**
10
16
  * Read the **current** search params from `window.location`, with support for detecting React's HashRouter.
11
17
  * Also returns a method that will yield the href (string) value, after any changes made on the params object.
12
18
  *
13
19
  * @returns The `URLSearchParams` instance, and a function that can be used to get an updated href.
14
20
  */ const getSearchParams = ()=>{
15
- const href = window.location.href;
16
- const searchStart = indexOfSearch(href);
17
- return new URLSearchParams(searchStart < 0 ? undefined : href.substring(searchStart));
21
+ const parts = extractParts(window.location.href);
22
+ return new URLSearchParams(parts[searchIndex(parts)]);
18
23
  };
19
24
  /**
20
25
  * Apply the search params to the current location, using `replaceState` (no navigation history).
@@ -23,13 +28,12 @@ import { useMemo, useState } from 'react';
23
28
  * @param params The parameters to apply.
24
29
  */ const applySearchParams = (params)=>{
25
30
  const currentHref = window.location.href;
26
- const index = indexOfSearch(currentHref);
27
- let nextHref = index < 0 ? currentHref : currentHref.substring(0, index);
28
- if (params.size > 0) {
29
- nextHref = nextHref.concat('?', params.toString());
30
- }
31
- if (nextHref !== currentHref) {
32
- window.history.replaceState(null, '', nextHref);
31
+ const parts = extractParts(currentHref);
32
+ const search = params.size > 0 ? `?${params.toString()}` : '';
33
+ const index = searchIndex(parts);
34
+ if (parts[index] !== search) {
35
+ parts[index] = search;
36
+ window.history.replaceState(null, '', parts.join(''));
33
37
  }
34
38
  };
35
39
  const getInitialState = (options)=>options.initialState instanceof Function ? options.initialState() : options.initialState;
@@ -43,14 +47,18 @@ export const useUrlSyncedState = (options)=>{
43
47
  const initialStateSerialized = useMemo(()=>{
44
48
  const stateMap = new Map();
45
49
  let initialize = null;
50
+ let needsApply = false;
46
51
  for (const [key, value, alwaysEmit] of options.serializer(getInitialState(options))){
47
52
  stateMap.set(key, value);
48
- if (alwaysEmit && value) {
53
+ if (sync && alwaysEmit && value) {
49
54
  initialize ?? (initialize = getSearchParams());
50
- initialize.set(key, value);
55
+ if (!initialize.has(key)) {
56
+ needsApply = true;
57
+ initialize.set(key, value);
58
+ }
51
59
  }
52
60
  }
53
- if (initialize) {
61
+ if (needsApply) {
54
62
  applySearchParams(initialize);
55
63
  }
56
64
  return stateMap;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/components/table/use-url-synced-state.ts"],"sourcesContent":["import {Dispatch, SetStateAction, useMemo, useState} from 'react';\n\n/**\n * A search param entry defines the encoded value of a search parameter as `[key, value, alwaysEmit?]`.\n * The third entry is an optional boolean that defaults to `false`.\n * Setting `alwaysEmit` to `true` means any non-nullish value is always written to the search params,\n * even if it matches the initial value. It is also written on initialization.\n */\nexport type SearchParamEntry = [string, string | null | undefined, boolean?];\n\n/**\n * Get the index of the ? in a URL that denotes the start of the \"search\".\n * Performs a nested search for '#/', to detect hash router urls and take the params of the hash in that case.\n *\n * @param url The URL to search.\n * @returns The location of the question mark, or `-1` if not found.\n */\nconst indexOfSearch = (url: string): number => url.indexOf('?', url.indexOf('#/') + 1);\n\n/**\n * Read the **current** search params from `window.location`, with support for detecting React's HashRouter.\n * Also returns a method that will yield the href (string) value, after any changes made on the params object.\n *\n * @returns The `URLSearchParams` instance, and a function that can be used to get an updated href.\n */\nconst getSearchParams = (): URLSearchParams => {\n const href = window.location.href;\n const searchStart = indexOfSearch(href);\n return new URLSearchParams(searchStart < 0 ? undefined : href.substring(searchStart));\n};\n\n/**\n * Apply the search params to the current location, using `replaceState` (no navigation history).\n * Note that only parameters in the `params` argument will be set, any other current params will be removed.\n *\n * @param params The parameters to apply.\n */\nconst applySearchParams = (params: URLSearchParams): void => {\n const currentHref = window.location.href;\n const index = indexOfSearch(currentHref);\n let nextHref = index < 0 ? currentHref : currentHref.substring(0, index);\n if (params.size > 0) {\n nextHref = nextHref.concat('?', params.toString());\n }\n if (nextHref !== currentHref) {\n window.history.replaceState(null, '', nextHref);\n }\n};\n\nexport interface UseUrlSyncedStateOptions<T> {\n /**\n * The initial state to use, if there would be no search params to deserialize from.\n * These values are also treated as defaults, and if the current state matches the initialState,\n * no value will be written to the search params.\n */\n initialState: T | (() => T);\n /**\n * The serializer function is used to determine how the state is translated to url search parameters.\n * Called each time the state changes.\n * Note that the serializer should always return entries for keys it controls, also if the current value is \"unset\" (`null` or empty).\n * This ensures params get removed from the search when they are being unset.\n *\n * @param stateValue The new state value to serialize.\n * @returns An iterable of `[key, value]` to set as url search parameters.\n * @example (filterValue) => [['filter', filterValue]] // ?filter=filterValue\n */\n serializer: (stateValue: T) => Iterable<SearchParamEntry>;\n /**\n * The deserializer function is used to determine how the url parameters influence the initial state.\n * May return a partial state, values that are not deserialed are taken from the `initialState`.\n * Called only once when initializing the state.\n * @param params All the search parameters of the current url.\n * @param initialState The initialState, can be used to take defaults from.\n * @returns The initial state based on the current url.\n * @example (params) => params.get('filter') ?? '',\n */\n deserializer: (params: URLSearchParams, initialState: T) => T;\n /**\n * Whether the state should be synced with the url, defaults to `true`.\n * When set to `false`, the hook behaves just like a regular `useState` hook from react.\n */\n sync?: boolean;\n}\n\nconst getInitialState = <T>(options: UseUrlSyncedStateOptions<T>): T =>\n options.initialState instanceof Function ? options.initialState() : options.initialState;\n\nexport const useUrlSyncedState = <T>(options: UseUrlSyncedStateOptions<T>) => {\n const sync = options.sync !== false;\n const [state, setState] = useState<T>(() => {\n const initialState = getInitialState(options);\n return sync ? options.deserializer(getSearchParams(), initialState) : initialState;\n });\n // Capture the initial state as a map (first render only!), to compare values and see if they should be set to the params.\n const initialStateSerialized = useMemo(() => {\n const stateMap = new Map<string, string>();\n let initialize: URLSearchParams | null = null;\n for (const [key, value, alwaysEmit] of options.serializer(getInitialState(options))) {\n stateMap.set(key, value);\n if (alwaysEmit && value) {\n initialize ??= getSearchParams();\n initialize.set(key, value);\n }\n }\n if (initialize) {\n applySearchParams(initialize);\n }\n return stateMap;\n }, []);\n\n const enhancedSetState = useMemo<Dispatch<SetStateAction<T>>>(() => {\n if (!sync) {\n return setState;\n }\n return (updater: SetStateAction<T>) => {\n setState((old) => {\n const newValue = updater instanceof Function ? updater(old) : updater;\n\n const search = getSearchParams();\n for (const [key, value, alwaysEmit] of options.serializer(newValue)) {\n if (value && (alwaysEmit || !Object.is(initialStateSerialized.get(key), value))) {\n search.set(key, value);\n } else {\n search.delete(key);\n }\n }\n applySearchParams(search);\n\n return newValue;\n });\n };\n }, [sync]);\n\n return [state, enhancedSetState] as const;\n};\n"],"names":["useMemo","useState","indexOfSearch","url","indexOf","getSearchParams","href","window","location","searchStart","URLSearchParams","undefined","substring","applySearchParams","params","currentHref","index","nextHref","size","concat","toString","history","replaceState","getInitialState","options","initialState","Function","useUrlSyncedState","sync","state","setState","deserializer","initialStateSerialized","stateMap","Map","initialize","key","value","alwaysEmit","serializer","set","enhancedSetState","updater","old","newValue","search","Object","is","get","delete"],"mappings":"AAAA,SAAkCA,OAAO,EAAEC,QAAQ,QAAO,QAAQ;AAUlE;;;;;;CAMC,GACD,MAAMC,gBAAgB,CAACC,MAAwBA,IAAIC,OAAO,CAAC,KAAKD,IAAIC,OAAO,CAAC,QAAQ;AAEpF;;;;;CAKC,GACD,MAAMC,kBAAkB;IACpB,MAAMC,OAAOC,OAAOC,QAAQ,CAACF,IAAI;IACjC,MAAMG,cAAcP,cAAcI;IAClC,OAAO,IAAII,gBAAgBD,cAAc,IAAIE,YAAYL,KAAKM,SAAS,CAACH;AAC5E;AAEA;;;;;CAKC,GACD,MAAMI,oBAAoB,CAACC;IACvB,MAAMC,cAAcR,OAAOC,QAAQ,CAACF,IAAI;IACxC,MAAMU,QAAQd,cAAca;IAC5B,IAAIE,WAAWD,QAAQ,IAAID,cAAcA,YAAYH,SAAS,CAAC,GAAGI;IAClE,IAAIF,OAAOI,IAAI,GAAG,GAAG;QACjBD,WAAWA,SAASE,MAAM,CAAC,KAAKL,OAAOM,QAAQ;IACnD;IACA,IAAIH,aAAaF,aAAa;QAC1BR,OAAOc,OAAO,CAACC,YAAY,CAAC,MAAM,IAAIL;IAC1C;AACJ;AAqCA,MAAMM,kBAAkB,CAAIC,UACxBA,QAAQC,YAAY,YAAYC,WAAWF,QAAQC,YAAY,KAAKD,QAAQC,YAAY;AAE5F,OAAO,MAAME,oBAAoB,CAAIH;IACjC,MAAMI,OAAOJ,QAAQI,IAAI,KAAK;IAC9B,MAAM,CAACC,OAAOC,SAAS,GAAG7B,SAAY;QAClC,MAAMwB,eAAeF,gBAAgBC;QACrC,OAAOI,OAAOJ,QAAQO,YAAY,CAAC1B,mBAAmBoB,gBAAgBA;IAC1E;IACA,0HAA0H;IAC1H,MAAMO,yBAAyBhC,QAAQ;QACnC,MAAMiC,WAAW,IAAIC;QACrB,IAAIC,aAAqC;QACzC,KAAK,MAAM,CAACC,KAAKC,OAAOC,WAAW,IAAId,QAAQe,UAAU,CAAChB,gBAAgBC,UAAW;YACjFS,SAASO,GAAG,CAACJ,KAAKC;YAClB,IAAIC,cAAcD,OAAO;gBACrBF,eAAAA,aAAe9B;gBACf8B,WAAWK,GAAG,CAACJ,KAAKC;YACxB;QACJ;QACA,IAAIF,YAAY;YACZtB,kBAAkBsB;QACtB;QACA,OAAOF;IACX,GAAG,EAAE;IAEL,MAAMQ,mBAAmBzC,QAAqC;QAC1D,IAAI,CAAC4B,MAAM;YACP,OAAOE;QACX;QACA,OAAO,CAACY;YACJZ,SAAS,CAACa;gBACN,MAAMC,WAAWF,mBAAmBhB,WAAWgB,QAAQC,OAAOD;gBAE9D,MAAMG,SAASxC;gBACf,KAAK,MAAM,CAAC+B,KAAKC,OAAOC,WAAW,IAAId,QAAQe,UAAU,CAACK,UAAW;oBACjE,IAAIP,SAAUC,CAAAA,cAAc,CAACQ,OAAOC,EAAE,CAACf,uBAAuBgB,GAAG,CAACZ,MAAMC,MAAK,GAAI;wBAC7EQ,OAAOL,GAAG,CAACJ,KAAKC;oBACpB,OAAO;wBACHQ,OAAOI,MAAM,CAACb;oBAClB;gBACJ;gBACAvB,kBAAkBgC;gBAElB,OAAOD;YACX;QACJ;IACJ,GAAG;QAAChB;KAAK;IAET,OAAO;QAACC;QAAOY;KAAiB;AACpC,EAAE"}
1
+ {"version":3,"sources":["../../../../src/components/table/use-url-synced-state.ts"],"sourcesContent":["import {Dispatch, SetStateAction, useMemo, useState} from 'react';\n\n/**\n * A search param entry defines the encoded value of a search parameter as `[key, value, alwaysEmit?]`.\n * The third entry is an optional boolean that defaults to `false`.\n * Setting `alwaysEmit` to `true` means any non-nullish value is always written to the search params,\n * even if it matches the initial value. It is also written on initialization.\n */\nexport type SearchParamEntry = [string, string | null | undefined, boolean?];\n\n/** A URL split into an array of length 4, as [pathname, search, hash, hashSearch] */\ntype UrlParts = [string, string, string, string];\n\nconst slice = Function.prototype.call.bind(Array.prototype.slice) as <T>(\n from: ArrayLike<T>,\n start?: number,\n end?: number,\n) => T[];\n\n/**\n * Split a url into its parts.\n *\n * @param href The url to extract the parts from.\n * @returns The separate parts, all are an empty string if not present.\n */\nconst extractParts = (href: string) => slice(/^([^?#]*)(\\?[^#]*|)(#[^?]*|)(\\?.*|)$/.exec(href ?? ''), 1, 5) as UrlParts;\n\n/**\n * The index of the search parameter to use, e.g. hashSearch for hash routes (hash starts with '#/').\n *\n * @param parts: The url parts, as returned by `extractParts`.\n * @returns The index of the search parameter to use (1 or 3).\n */\nconst searchIndex = (parts: UrlParts): 1 | 3 => (/^#\\//.test(parts[2]) ? 3 : 1);\n\n/**\n * Read the **current** search params from `window.location`, with support for detecting React's HashRouter.\n * Also returns a method that will yield the href (string) value, after any changes made on the params object.\n *\n * @returns The `URLSearchParams` instance, and a function that can be used to get an updated href.\n */\nconst getSearchParams = (): URLSearchParams => {\n const parts = extractParts(window.location.href);\n return new URLSearchParams(parts[searchIndex(parts)]);\n};\n\n/**\n * Apply the search params to the current location, using `replaceState` (no navigation history).\n * Note that only parameters in the `params` argument will be set, any other current params will be removed.\n *\n * @param params The parameters to apply.\n */\nconst applySearchParams = (params: URLSearchParams): void => {\n const currentHref = window.location.href;\n const parts = extractParts(currentHref);\n const search = params.size > 0 ? `?${params.toString()}` : '';\n const index = searchIndex(parts);\n if (parts[index] !== search) {\n parts[index] = search;\n window.history.replaceState(null, '', parts.join(''));\n }\n};\n\nexport interface UseUrlSyncedStateOptions<T> {\n /**\n * The initial state to use, if there would be no search params to deserialize from.\n * These values are also treated as defaults, and if the current state matches the initialState,\n * no value will be written to the search params.\n */\n initialState: T | (() => T);\n /**\n * The serializer function is used to determine how the state is translated to url search parameters.\n * Called each time the state changes.\n * Note that the serializer should always return entries for keys it controls, also if the current value is \"unset\" (`null` or empty).\n * This ensures params get removed from the search when they are being unset.\n *\n * @param stateValue The new state value to serialize.\n * @returns An iterable of `[key, value]` to set as url search parameters.\n * @example (filterValue) => [['filter', filterValue]] // ?filter=filterValue\n */\n serializer: (stateValue: T) => Iterable<SearchParamEntry>;\n /**\n * The deserializer function is used to determine how the url parameters influence the initial state.\n * May return a partial state, values that are not deserialed are taken from the `initialState`.\n * Called only once when initializing the state.\n * @param params All the search parameters of the current url.\n * @param initialState The initialState, can be used to take defaults from.\n * @returns The initial state based on the current url.\n * @example (params) => params.get('filter') ?? '',\n */\n deserializer: (params: URLSearchParams, initialState: T) => T;\n /**\n * Whether the state should be synced with the url, defaults to `true`.\n * When set to `false`, the hook behaves just like a regular `useState` hook from react.\n */\n sync?: boolean;\n}\n\nconst getInitialState = <T>(options: UseUrlSyncedStateOptions<T>): T =>\n options.initialState instanceof Function ? options.initialState() : options.initialState;\n\nexport const useUrlSyncedState = <T>(options: UseUrlSyncedStateOptions<T>) => {\n const sync = options.sync !== false;\n const [state, setState] = useState<T>(() => {\n const initialState = getInitialState(options);\n return sync ? options.deserializer(getSearchParams(), initialState) : initialState;\n });\n // Capture the initial state as a map (first render only!), to compare values and see if they should be set to the params.\n const initialStateSerialized = useMemo(() => {\n const stateMap = new Map<string, string>();\n let initialize: URLSearchParams | null = null;\n let needsApply = false;\n for (const [key, value, alwaysEmit] of options.serializer(getInitialState(options))) {\n stateMap.set(key, value);\n if (sync && alwaysEmit && value) {\n initialize ??= getSearchParams();\n if (!initialize.has(key)) {\n needsApply = true;\n initialize.set(key, value);\n }\n }\n }\n if (needsApply) {\n applySearchParams(initialize);\n }\n return stateMap;\n }, []);\n\n const enhancedSetState = useMemo<Dispatch<SetStateAction<T>>>(() => {\n if (!sync) {\n return setState;\n }\n return (updater: SetStateAction<T>) => {\n setState((old) => {\n const newValue = updater instanceof Function ? updater(old) : updater;\n\n const search = getSearchParams();\n for (const [key, value, alwaysEmit] of options.serializer(newValue)) {\n if (value && (alwaysEmit || !Object.is(initialStateSerialized.get(key), value))) {\n search.set(key, value);\n } else {\n search.delete(key);\n }\n }\n applySearchParams(search);\n\n return newValue;\n });\n };\n }, [sync]);\n\n return [state, enhancedSetState] as const;\n};\n"],"names":["useMemo","useState","slice","Function","prototype","call","bind","Array","extractParts","href","exec","searchIndex","parts","test","getSearchParams","window","location","URLSearchParams","applySearchParams","params","currentHref","search","size","toString","index","history","replaceState","join","getInitialState","options","initialState","useUrlSyncedState","sync","state","setState","deserializer","initialStateSerialized","stateMap","Map","initialize","needsApply","key","value","alwaysEmit","serializer","set","has","enhancedSetState","updater","old","newValue","Object","is","get","delete"],"mappings":"AAAA,SAAkCA,OAAO,EAAEC,QAAQ,QAAO,QAAQ;AAalE,MAAMC,QAAQC,SAASC,SAAS,CAACC,IAAI,CAACC,IAAI,CAACC,MAAMH,SAAS,CAACF,KAAK;AAMhE;;;;;CAKC,GACD,MAAMM,eAAe,CAACC,OAAiBP,MAAM,uCAAuCQ,IAAI,CAACD,QAAQ,KAAK,GAAG;AAEzG;;;;;CAKC,GACD,MAAME,cAAc,CAACC,QAA4B,OAAOC,IAAI,CAACD,KAAK,CAAC,EAAE,IAAI,IAAI;AAE7E;;;;;CAKC,GACD,MAAME,kBAAkB;IACpB,MAAMF,QAAQJ,aAAaO,OAAOC,QAAQ,CAACP,IAAI;IAC/C,OAAO,IAAIQ,gBAAgBL,KAAK,CAACD,YAAYC,OAAO;AACxD;AAEA;;;;;CAKC,GACD,MAAMM,oBAAoB,CAACC;IACvB,MAAMC,cAAcL,OAAOC,QAAQ,CAACP,IAAI;IACxC,MAAMG,QAAQJ,aAAaY;IAC3B,MAAMC,SAASF,OAAOG,IAAI,GAAG,IAAI,CAAC,CAAC,EAAEH,OAAOI,QAAQ,IAAI,GAAG;IAC3D,MAAMC,QAAQb,YAAYC;IAC1B,IAAIA,KAAK,CAACY,MAAM,KAAKH,QAAQ;QACzBT,KAAK,CAACY,MAAM,GAAGH;QACfN,OAAOU,OAAO,CAACC,YAAY,CAAC,MAAM,IAAId,MAAMe,IAAI,CAAC;IACrD;AACJ;AAqCA,MAAMC,kBAAkB,CAAIC,UACxBA,QAAQC,YAAY,YAAY3B,WAAW0B,QAAQC,YAAY,KAAKD,QAAQC,YAAY;AAE5F,OAAO,MAAMC,oBAAoB,CAAIF;IACjC,MAAMG,OAAOH,QAAQG,IAAI,KAAK;IAC9B,MAAM,CAACC,OAAOC,SAAS,GAAGjC,SAAY;QAClC,MAAM6B,eAAeF,gBAAgBC;QACrC,OAAOG,OAAOH,QAAQM,YAAY,CAACrB,mBAAmBgB,gBAAgBA;IAC1E;IACA,0HAA0H;IAC1H,MAAMM,yBAAyBpC,QAAQ;QACnC,MAAMqC,WAAW,IAAIC;QACrB,IAAIC,aAAqC;QACzC,IAAIC,aAAa;QACjB,KAAK,MAAM,CAACC,KAAKC,OAAOC,WAAW,IAAId,QAAQe,UAAU,CAAChB,gBAAgBC,UAAW;YACjFQ,SAASQ,GAAG,CAACJ,KAAKC;YAClB,IAAIV,QAAQW,cAAcD,OAAO;gBAC7BH,eAAAA,aAAezB;gBACf,IAAI,CAACyB,WAAWO,GAAG,CAACL,MAAM;oBACtBD,aAAa;oBACbD,WAAWM,GAAG,CAACJ,KAAKC;gBACxB;YACJ;QACJ;QACA,IAAIF,YAAY;YACZtB,kBAAkBqB;QACtB;QACA,OAAOF;IACX,GAAG,EAAE;IAEL,MAAMU,mBAAmB/C,QAAqC;QAC1D,IAAI,CAACgC,MAAM;YACP,OAAOE;QACX;QACA,OAAO,CAACc;YACJd,SAAS,CAACe;gBACN,MAAMC,WAAWF,mBAAmB7C,WAAW6C,QAAQC,OAAOD;gBAE9D,MAAM3B,SAASP;gBACf,KAAK,MAAM,CAAC2B,KAAKC,OAAOC,WAAW,IAAId,QAAQe,UAAU,CAACM,UAAW;oBACjE,IAAIR,SAAUC,CAAAA,cAAc,CAACQ,OAAOC,EAAE,CAAChB,uBAAuBiB,GAAG,CAACZ,MAAMC,MAAK,GAAI;wBAC7ErB,OAAOwB,GAAG,CAACJ,KAAKC;oBACpB,OAAO;wBACHrB,OAAOiC,MAAM,CAACb;oBAClB;gBACJ;gBACAvB,kBAAkBG;gBAElB,OAAO6B;YACX;QACJ;IACJ,GAAG;QAAClB;KAAK;IAET,OAAO;QAACC;QAAOc;KAAiB;AACpC,EAAE"}
@@ -11,7 +11,7 @@ export { type NotificationsProps } from '@mantine/notifications';
11
11
  export * from '@tanstack/table-core';
12
12
  export * from './components';
13
13
  export { noop };
14
- export { ActionIcon, BrowserPreview, Button, CopyToClipboard, Header, Menu, PasswordInput, Select, Table, type ActionIconProps, type ButtonProps, type CopyToClipboardProps, type HeaderProps, type MenuItemProps, type TableProps, type TableState, } from './components';
14
+ export { ActionIcon, BrowserPreview, Button, CopyToClipboard, Header, Menu, Modal, PasswordInput, Select, Table, type ActionIconProps, type ButtonProps, type CopyToClipboardProps, type HeaderProps, type MenuItemProps, type ModalFactory, type TableProps, type TableState, } from './components';
15
15
  export * from './theme';
16
16
  declare module '@mantine/core' {
17
17
  interface MantineThemeColorsOverride {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,kBAAkB,EAAE,IAAI,EAAC,MAAM,eAAe,CAAC;AACvD,OAAO,EAAC,KAAK,OAAO,EAAC,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAC,KAAK,YAAY,EAAC,MAAM,sBAAsB,CAAC;AAEvD,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAC,UAAU,EAAC,MAAM,eAAe,CAAC;AACzC,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC;AACvC,OAAO,EAAC,KAAK,kBAAkB,EAAC,MAAM,wBAAwB,CAAC;AAC/D,cAAc,sBAAsB,CAAC;AACrC,cAAc,cAAc,CAAC;AAC7B,OAAO,EAAC,IAAI,EAAC,CAAC;AAGd,OAAO,EACH,UAAU,EACV,cAAc,EACd,MAAM,EACN,eAAe,EACf,MAAM,EACN,IAAI,EACJ,aAAa,EACb,MAAM,EACN,KAAK,EACL,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,oBAAoB,EACzB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,UAAU,EACf,KAAK,UAAU,GAClB,MAAM,cAAc,CAAC;AAEtB,cAAc,SAAS,CAAC;AAExB,OAAO,QAAQ,eAAe,CAAC;IAC3B,UAAiB,0BAA0B;QACvC,MAAM,EAAE,MAAM,CAAC,MAAM,OAAO,YAAY,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,EAAE,kBAAkB,CAAC,CAAC;KACjF;CACJ;AAED,OAAO,QAAQ,uBAAuB,CAAC;IACnC,UAAU,UAAU,CAAC,KAAK,SAAS,OAAO,EAAE,MAAM;QAC9C;;;;WAIG;QACH,aAAa,EAAE,OAAO,CAAC;KAC1B;CACJ"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,kBAAkB,EAAE,IAAI,EAAC,MAAM,eAAe,CAAC;AACvD,OAAO,EAAC,KAAK,OAAO,EAAC,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAC,KAAK,YAAY,EAAC,MAAM,sBAAsB,CAAC;AAEvD,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAC,UAAU,EAAC,MAAM,eAAe,CAAC;AACzC,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC;AACvC,OAAO,EAAC,KAAK,kBAAkB,EAAC,MAAM,wBAAwB,CAAC;AAC/D,cAAc,sBAAsB,CAAC;AACrC,cAAc,cAAc,CAAC;AAC7B,OAAO,EAAC,IAAI,EAAC,CAAC;AAGd,OAAO,EACH,UAAU,EACV,cAAc,EACd,MAAM,EACN,eAAe,EACf,MAAM,EACN,IAAI,EACJ,KAAK,EACL,aAAa,EACb,MAAM,EACN,KAAK,EACL,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,oBAAoB,EACzB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,UAAU,GAClB,MAAM,cAAc,CAAC;AAEtB,cAAc,SAAS,CAAC;AAExB,OAAO,QAAQ,eAAe,CAAC;IAC3B,UAAiB,0BAA0B;QACvC,MAAM,EAAE,MAAM,CAAC,MAAM,OAAO,YAAY,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,EAAE,kBAAkB,CAAC,CAAC;KACjF;CACJ;AAED,OAAO,QAAQ,uBAAuB,CAAC;IACnC,UAAU,UAAU,CAAC,KAAK,SAAS,OAAO,EAAE,MAAM;QAC9C;;;;WAIG;QACH,aAAa,EAAE,OAAO,CAAC;KAC1B;CACJ"}
package/dist/esm/index.js CHANGED
@@ -9,7 +9,7 @@ export * from '@tanstack/table-core';
9
9
  export * from './components';
10
10
  export { noop };
11
11
  // explicitly overriding mantine components
12
- export { ActionIcon, BrowserPreview, Button, CopyToClipboard, Header, Menu, PasswordInput, Select, Table } from './components';
12
+ export { ActionIcon, BrowserPreview, Button, CopyToClipboard, Header, Menu, Modal, PasswordInput, Select, Table } from './components';
13
13
  export * from './theme';
14
14
 
15
15
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/index.ts"],"sourcesContent":["import {MantineColorsTuple, noop} from '@mantine/core';\nimport {type RowData} from '@tanstack/table-core';\nimport {type PlasmaColors} from './theme/PlasmaColors';\n\nexport * from '@mantine/carousel';\nexport * from '@mantine/core';\nexport {Pagination} from '@mantine/core';\nexport * from '@mantine/form';\nexport * from '@mantine/hooks';\nexport * from '@mantine/notifications';\nexport {type NotificationsProps} from '@mantine/notifications';\nexport * from '@tanstack/table-core';\nexport * from './components';\nexport {noop};\n\n// explicitly overriding mantine components\nexport {\n ActionIcon,\n BrowserPreview,\n Button,\n CopyToClipboard,\n Header,\n Menu,\n PasswordInput,\n Select,\n Table,\n type ActionIconProps,\n type ButtonProps,\n type CopyToClipboardProps,\n type HeaderProps,\n type MenuItemProps,\n type TableProps,\n type TableState,\n} from './components';\n\nexport * from './theme';\n\ndeclare module '@mantine/core' {\n export interface MantineThemeColorsOverride {\n colors: Record<keyof typeof PlasmaColors | (string & {}), MantineColorsTuple>;\n }\n}\n\ndeclare module '@tanstack/react-table' {\n interface ColumnMeta<TData extends RowData, TValue> {\n /**\n * Whether the column is a control column.\n * Control columns are columns that are not part of the data but are used to control the table.\n * For example, a column that contains checkboxes to select rows.\n */\n controlColumn: boolean;\n }\n}\n"],"names":["noop","Pagination","ActionIcon","BrowserPreview","Button","CopyToClipboard","Header","Menu","PasswordInput","Select","Table"],"mappings":"AAAA,SAA4BA,IAAI,QAAO,gBAAgB;AAIvD,cAAc,oBAAoB;AAClC,cAAc,gBAAgB;AAC9B,SAAQC,UAAU,QAAO,gBAAgB;AACzC,cAAc,gBAAgB;AAC9B,cAAc,iBAAiB;AAC/B,cAAc,yBAAyB;AAEvC,cAAc,uBAAuB;AACrC,cAAc,eAAe;AAC7B,SAAQD,IAAI,GAAE;AAEd,2CAA2C;AAC3C,SACIE,UAAU,EACVC,cAAc,EACdC,MAAM,EACNC,eAAe,EACfC,MAAM,EACNC,IAAI,EACJC,aAAa,EACbC,MAAM,EACNC,KAAK,QAQF,eAAe;AAEtB,cAAc,UAAU"}
1
+ {"version":3,"sources":["../../src/index.ts"],"sourcesContent":["import {MantineColorsTuple, noop} from '@mantine/core';\nimport {type RowData} from '@tanstack/table-core';\nimport {type PlasmaColors} from './theme/PlasmaColors';\n\nexport * from '@mantine/carousel';\nexport * from '@mantine/core';\nexport {Pagination} from '@mantine/core';\nexport * from '@mantine/form';\nexport * from '@mantine/hooks';\nexport * from '@mantine/notifications';\nexport {type NotificationsProps} from '@mantine/notifications';\nexport * from '@tanstack/table-core';\nexport * from './components';\nexport {noop};\n\n// explicitly overriding mantine components\nexport {\n ActionIcon,\n BrowserPreview,\n Button,\n CopyToClipboard,\n Header,\n Menu,\n Modal,\n PasswordInput,\n Select,\n Table,\n type ActionIconProps,\n type ButtonProps,\n type CopyToClipboardProps,\n type HeaderProps,\n type MenuItemProps,\n type ModalFactory,\n type TableProps,\n type TableState,\n} from './components';\n\nexport * from './theme';\n\ndeclare module '@mantine/core' {\n export interface MantineThemeColorsOverride {\n colors: Record<keyof typeof PlasmaColors | (string & {}), MantineColorsTuple>;\n }\n}\n\ndeclare module '@tanstack/react-table' {\n interface ColumnMeta<TData extends RowData, TValue> {\n /**\n * Whether the column is a control column.\n * Control columns are columns that are not part of the data but are used to control the table.\n * For example, a column that contains checkboxes to select rows.\n */\n controlColumn: boolean;\n }\n}\n"],"names":["noop","Pagination","ActionIcon","BrowserPreview","Button","CopyToClipboard","Header","Menu","Modal","PasswordInput","Select","Table"],"mappings":"AAAA,SAA4BA,IAAI,QAAO,gBAAgB;AAIvD,cAAc,oBAAoB;AAClC,cAAc,gBAAgB;AAC9B,SAAQC,UAAU,QAAO,gBAAgB;AACzC,cAAc,gBAAgB;AAC9B,cAAc,iBAAiB;AAC/B,cAAc,yBAAyB;AAEvC,cAAc,uBAAuB;AACrC,cAAc,eAAe;AAC7B,SAAQD,IAAI,GAAE;AAEd,2CAA2C;AAC3C,SACIE,UAAU,EACVC,cAAc,EACdC,MAAM,EACNC,eAAe,EACfC,MAAM,EACNC,IAAI,EACJC,KAAK,EACLC,aAAa,EACbC,MAAM,EACNC,KAAK,QASF,eAAe;AAEtB,cAAc,UAAU"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coveord/plasma-mantine",
3
- "version": "55.6.0",
3
+ "version": "55.7.1",
4
4
  "description": "A Plasma flavoured Mantine theme",
5
5
  "keywords": [
6
6
  "plasma",
@@ -27,57 +27,57 @@
27
27
  "main": "./dist/cjs/index.js",
28
28
  "module": "./dist/esm/index.js",
29
29
  "dependencies": {
30
- "@dnd-kit/core": "6.2.0",
30
+ "@dnd-kit/core": "6.3.1",
31
31
  "@dnd-kit/modifiers": "9.0.0",
32
32
  "@dnd-kit/sortable": "10.0.0",
33
33
  "@dnd-kit/utilities": "3.2.2",
34
34
  "@mantine/utils": "6.0.22",
35
35
  "@monaco-editor/react": "4.6.0",
36
36
  "@swc/helpers": "0.5.15",
37
- "@tanstack/react-table": "8.20.5",
37
+ "@tanstack/react-table": "8.20.6",
38
38
  "@tanstack/table-core": "8.20.5",
39
39
  "clsx": "2.1.1",
40
40
  "dayjs": "1.11.13",
41
41
  "fast-deep-equal": "3.1.3",
42
42
  "lodash.debounce": "4.0.8",
43
43
  "lodash.defaultsdeep": "4.6.1",
44
- "monaco-editor": "0.52.0",
45
- "@coveord/plasma-react-icons": "55.4.0",
46
- "@coveord/plasma-tokens": "55.4.0"
44
+ "monaco-editor": "0.52.2",
45
+ "@coveord/plasma-react-icons": "55.7.1",
46
+ "@coveord/plasma-tokens": "55.7.1"
47
47
  },
48
48
  "devDependencies": {
49
- "@mantine/carousel": "7.14.3",
50
- "@mantine/code-highlight": "7.14.3",
51
- "@mantine/core": "7.14.3",
52
- "@mantine/dates": "7.14.3",
53
- "@mantine/form": "7.14.3",
54
- "@mantine/hooks": "7.14.3",
55
- "@mantine/modals": "7.14.3",
56
- "@mantine/notifications": "7.14.3",
57
- "@swc/cli": "0.5.2",
58
- "@swc/core": "1.9.3",
49
+ "@mantine/carousel": "7.16.1",
50
+ "@mantine/code-highlight": "7.16.1",
51
+ "@mantine/core": "7.16.1",
52
+ "@mantine/dates": "7.16.1",
53
+ "@mantine/form": "7.16.1",
54
+ "@mantine/hooks": "7.16.1",
55
+ "@mantine/modals": "7.16.1",
56
+ "@mantine/notifications": "7.16.1",
57
+ "@swc/cli": "0.6.0",
58
+ "@swc/core": "1.10.8",
59
59
  "@testing-library/dom": "10.4.0",
60
60
  "@testing-library/jest-dom": "6.6.3",
61
- "@testing-library/react": "16.0.1",
62
- "@testing-library/user-event": "14.5.2",
61
+ "@testing-library/react": "16.2.0",
62
+ "@testing-library/user-event": "14.6.0",
63
63
  "@types/lodash.debounce": "4.0.9",
64
64
  "@types/lodash.defaultsdeep": "4.6.9",
65
- "@types/react": "18.3.12",
66
- "@types/react-dom": "18.3.1",
65
+ "@types/react": "18.3.18",
66
+ "@types/react-dom": "18.3.5",
67
67
  "embla-carousel-react": "7.1.0",
68
68
  "identity-obj-proxy": "3.0.0",
69
69
  "jsdom": "26.0.0",
70
- "postcss": "8.4.49",
70
+ "postcss": "8.5.1",
71
71
  "postcss-preset-mantine": "^1.11.0",
72
72
  "postcss-simple-vars": "^7.0.1",
73
- "publint": "0.2.12",
73
+ "publint": "0.3.2",
74
74
  "react": "18.3.1",
75
75
  "react-dom": "18.3.1",
76
76
  "rimraf": "6.0.1",
77
- "sass": "1.81.1",
77
+ "sass": "1.83.4",
78
78
  "tslib": "2.8.1",
79
- "typescript": "5.7.2",
80
- "vitest": "2.1.8"
79
+ "typescript": "5.7.3",
80
+ "vitest": "3.0.5"
81
81
  },
82
82
  "peerDependencies": {
83
83
  "@mantine/carousel": "^7.6.1",
@@ -72,6 +72,12 @@ interface CodeEditorProps
72
72
  * @default 'local'
73
73
  */
74
74
  monacoLoader?: 'cdn' | 'local';
75
+ /**
76
+ * Options to pass to the monaco editor.
77
+ * Currently only supporting [`tabSize`](https://microsoft.github.io/monaco-editor/typedoc/interfaces/editor.IStandaloneEditorConstructionOptions.html#tabSize).
78
+ *
79
+ */
80
+ options?: Pick<monacoEditor.IStandaloneEditorConstructionOptions, 'tabSize'>;
75
81
  }
76
82
 
77
83
  const defaultProps: Partial<CodeEditorProps> = {
@@ -101,6 +107,7 @@ export const CodeEditor: FunctionComponent<CodeEditorProps> = (props) => {
101
107
  maxHeight,
102
108
  disabled,
103
109
  monacoLoader,
110
+ options: {tabSize} = {tabSize: 2},
104
111
  ...others
105
112
  } = useProps('CodeEditor', defaultProps, props);
106
113
  const [loaded, setLoaded] = useState(false);
@@ -230,7 +237,7 @@ export const CodeEditor: FunctionComponent<CodeEditorProps> = (props) => {
230
237
  formatOnPaste: true,
231
238
  fontSize: px(theme.fontSizes.xs) as number,
232
239
  readOnly: disabled,
233
- tabSize: 2,
240
+ tabSize,
234
241
  }}
235
242
  value={_value}
236
243
  onChange={handleChange}
@@ -10,6 +10,7 @@ export * from './ellipsis-text';
10
10
  export * from './header';
11
11
  export * from './inline-confirm';
12
12
  export * from './menu';
13
+ export * from './modal';
13
14
  export * from './prompt';
14
15
  export * from './read-only';
15
16
  export * from './sticky-footer';
@@ -0,0 +1,9 @@
1
+ .footer {
2
+ border-top: 1px solid var(--mantine-color-gray-3);
3
+ }
4
+
5
+ .modalFooterSticky {
6
+ padding-bottom: 0;
7
+ margin: var(--mb-padding) calc(-1 * var(--mb-padding)) calc(var(--mantine-spacing-md) - var(--mb-padding))
8
+ calc(-1 * var(--mb-padding));
9
+ }
@@ -0,0 +1,33 @@
1
+ import {
2
+ factory,
3
+ Modal as MantineModal,
4
+ ModalFactory as MantineModalFactory,
5
+ ModalProps as MantineModalProps,
6
+ } from '@mantine/core';
7
+ import {ModalFooter as PlasmaModalFooter} from './ModalFooter';
8
+
9
+ // Need to redeclare the factory to override and add footer to the props type
10
+ type PlasmaModalFactory = Omit<MantineModalFactory, 'staticComponents'> & {
11
+ staticComponents: MantineModalFactory['staticComponents'] & {
12
+ Footer: typeof PlasmaModalFooter;
13
+ };
14
+ };
15
+
16
+ const PlasmaModal = factory<PlasmaModalFactory>((props: MantineModalProps, ref) => (
17
+ <MantineModal ref={ref} {...props} />
18
+ ));
19
+
20
+ PlasmaModal.displayName = '@coveord/plasma-mantine/Modal';
21
+ PlasmaModal.Root = MantineModal.Root;
22
+ PlasmaModal.Body = MantineModal.Body;
23
+ PlasmaModal.Overlay = MantineModal.Overlay;
24
+ PlasmaModal.Content = MantineModal.Content;
25
+ PlasmaModal.Header = MantineModal.Header;
26
+ PlasmaModal.Title = MantineModal.Title;
27
+ PlasmaModal.CloseButton = MantineModal.CloseButton;
28
+ PlasmaModal.Stack = MantineModal.Stack;
29
+ PlasmaModal.Footer = PlasmaModalFooter;
30
+
31
+ export const Modal = PlasmaModal;
32
+
33
+ export type ModalFactory = PlasmaModalFactory;
@@ -0,0 +1,47 @@
1
+ import {useRef, useEffect} from 'react';
2
+ import clsx from 'clsx';
3
+ import {Factory, factory} from '@mantine/core';
4
+ import {StickyFooter, StickyFooterProps, StickyFooterStylesNames} from '../sticky-footer';
5
+ import classes from './Modal.module.css';
6
+
7
+ export interface ModalFooterProps extends Omit<StickyFooterProps, 'variant'> {
8
+ /**
9
+ * If the footer is sticky, its margin will be adjusted to counteract the padding of the Modal.Body, ensuring the footer visually sticks to the bottom of the modal.
10
+ */
11
+ sticky?: boolean;
12
+ }
13
+
14
+ export type ModalFooterStylesNames = StickyFooterStylesNames;
15
+
16
+ export type ModalFooterFactory = Factory<{
17
+ props: ModalFooterProps;
18
+ ref: HTMLDivElement;
19
+ stylesNames: ModalFooterStylesNames;
20
+ }>;
21
+
22
+ const ensuresFooterHasEvenHeight = (footer: HTMLElement) => {
23
+ const remainder = footer.offsetHeight % 2;
24
+ footer.style.height = `${footer.offsetHeight - remainder + 2}px`;
25
+ };
26
+
27
+ export const ModalFooter = factory<ModalFooterFactory>(({sticky, ...props}, ref) => {
28
+ const _ref = useRef<HTMLDivElement>();
29
+
30
+ const footerRef = ref || _ref;
31
+
32
+ useEffect(() => {
33
+ if (typeof footerRef !== 'function' && footerRef.current) {
34
+ ensuresFooterHasEvenHeight(footerRef.current);
35
+ }
36
+
37
+ // if ref === 'function', this is a callback ref. Haven't found any solution for adjusting the height in this case
38
+ }, [ref, props.h]);
39
+
40
+ return (
41
+ <StickyFooter
42
+ className={clsx(classes.footer, {[classes.modalFooterSticky]: !!sticky})}
43
+ ref={footerRef}
44
+ {...props}
45
+ />
46
+ );
47
+ });
@@ -0,0 +1,25 @@
1
+ import {render, screen} from '@test-utils';
2
+
3
+ import {Modal} from '../Modal';
4
+
5
+ // Since most part of the modal component directly inherits @mantine/core, many tests are likely covered by Mantine, so we only add tests about our customizations
6
+ describe('Modal', () => {
7
+ it('renders footer', () => {
8
+ render(
9
+ <Modal opened={true} onClose={vi.fn()}>
10
+ <Modal.Footer sticky>im the footer</Modal.Footer>
11
+ </Modal>,
12
+ );
13
+
14
+ expect(screen.getByText('im the footer')).toBeInTheDocument();
15
+ });
16
+ it('renders footer in root', () => {
17
+ render(
18
+ <Modal.Root opened={true} onClose={vi.fn()}>
19
+ <Modal.Footer>im the footer</Modal.Footer>
20
+ </Modal.Root>,
21
+ );
22
+
23
+ expect(screen.getByText('im the footer')).toBeInTheDocument();
24
+ });
25
+ });
@@ -0,0 +1,35 @@
1
+ import {render, screen} from '@test-utils';
2
+
3
+ import {Modal} from '../Modal';
4
+
5
+ describe('ModalFooter', () => {
6
+ it('renders children', () => {
7
+ render(
8
+ <Modal.Footer>
9
+ <div>im the children</div>
10
+ </Modal.Footer>,
11
+ );
12
+
13
+ expect(screen.getByText('im the children')).toBeInTheDocument();
14
+ });
15
+ it('includes the .modalFooterSticky class styling if set to sticky', () => {
16
+ render(
17
+ <Modal.Footer sticky>
18
+ <div>im the children</div>
19
+ </Modal.Footer>,
20
+ );
21
+
22
+ const footer = screen.getByText('im the children').parentElement;
23
+ expect(footer.className).contains('modalFooterSticky');
24
+ });
25
+ it('has an even height value to ensure the footer sticks completely to the bottom as a workaround to the footer positioning issue when height value is odd', () => {
26
+ render(
27
+ <Modal.Footer h={99}>
28
+ <div>im the children</div>
29
+ </Modal.Footer>,
30
+ );
31
+
32
+ const footer = screen.getByText('im the children').parentElement;
33
+ expect(footer.offsetHeight % 2).lessThanOrEqual(Number.EPSILON);
34
+ });
35
+ });
@@ -0,0 +1,2 @@
1
+ export * from './Modal';
2
+ export * from './ModalFooter';
@@ -4,7 +4,6 @@ import {
4
4
  factory,
5
5
  Factory,
6
6
  Image,
7
- Modal,
8
7
  ModalRootProps,
9
8
  ModalStylesNames,
10
9
  StylesApiProps,
@@ -12,6 +11,7 @@ import {
12
11
  useStyles,
13
12
  } from '@mantine/core';
14
13
  import {Children, ReactElement, ReactNode} from 'react';
14
+ import {Modal} from '../modal';
15
15
  import Critical from './icons/critical.svg';
16
16
  import Info from './icons/info.svg';
17
17
  import Success from './icons/success.svg';
@@ -20,7 +20,6 @@ import {PromptContextProvider} from './Prompt.context';
20
20
  import classes from './Prompt.module.css';
21
21
  import {PromptCancelButton, PromptCancelButtonStylesNamesVariant} from './PromptCancelButton';
22
22
  import {PromptConfirmButton, PromptConfirmButtonStylesNamesVariant} from './PromptConfirmButton';
23
- import {PromptFooter} from './PromptFooter';
24
23
 
25
24
  export type PromptVariant = 'success' | 'warning' | 'critical' | 'info';
26
25
  export type PromptVars = {root: '--prompt-icon-size'};
@@ -53,7 +52,7 @@ export type PromptFactory = Factory<{
53
52
  staticComponents: {
54
53
  CancelButton: typeof PromptCancelButton;
55
54
  ConfirmButton: typeof PromptConfirmButton;
56
- Footer: typeof PromptFooter;
55
+ Footer: typeof Modal.Footer;
57
56
  };
58
57
  }>;
59
58
 
@@ -92,10 +91,12 @@ export const Prompt = factory<PromptFactory>((_props, ref) => {
92
91
  });
93
92
  const stylesApiProps = {classNames, styles};
94
93
 
95
- const convertedChildren = Children.toArray(children) as ReactElement[];
94
+ const footers: ReactElement[] = [];
95
+ const otherChildren: ReactElement[] = [];
96
96
 
97
- const otherChildren = convertedChildren.filter((child) => child.type !== PromptFooter);
98
- const footer = convertedChildren.find((child) => child.type === PromptFooter);
97
+ Children.forEach(children, (child: ReactElement) => {
98
+ (child.type === Modal.Footer ? footers : otherChildren).push(child);
99
+ });
99
100
 
100
101
  return (
101
102
  <PromptContextProvider value={{variant, getStyles}}>
@@ -119,7 +120,7 @@ export const Prompt = factory<PromptFactory>((_props, ref) => {
119
120
  <Modal.Body {...getStyles('body', stylesApiProps)}>
120
121
  <Box {...getStyles('inner', stylesApiProps)}>{otherChildren}</Box>
121
122
  </Modal.Body>
122
- {footer}
123
+ {footers}
123
124
  </Modal.Content>
124
125
  </Modal.Root>
125
126
  </PromptContextProvider>
@@ -128,4 +129,4 @@ export const Prompt = factory<PromptFactory>((_props, ref) => {
128
129
 
129
130
  Prompt.CancelButton = PromptCancelButton;
130
131
  Prompt.ConfirmButton = PromptConfirmButton;
131
- Prompt.Footer = PromptFooter;
132
+ Prompt.Footer = Modal.Footer;