@linzjs/windows 10.3.1 → 11.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (223) hide show
  1. package/dist/LuiModalAsync/LuiModalAsync.d.ts +14 -0
  2. package/dist/LuiModalAsync/LuiModalAsync.js +45 -0
  3. package/dist/LuiModalAsync/LuiModalAsync.js.map +1 -0
  4. package/dist/LuiModalAsync/LuiModalAsync.scss +1 -2
  5. package/dist/LuiModalAsync/LuiModalAsyncButtonGroup.d.ts +19 -0
  6. package/dist/LuiModalAsync/LuiModalAsyncButtonGroup.js +27 -0
  7. package/dist/LuiModalAsync/LuiModalAsyncButtonGroup.js.map +1 -0
  8. package/dist/LuiModalAsync/LuiModalAsyncContent.d.ts +6 -0
  9. package/dist/LuiModalAsync/LuiModalAsyncContent.js +7 -0
  10. package/dist/LuiModalAsync/LuiModalAsyncContent.js.map +1 -0
  11. package/dist/LuiModalAsync/LuiModalAsyncContext.d.ts +28 -0
  12. package/dist/LuiModalAsync/LuiModalAsyncContext.js +9 -0
  13. package/dist/LuiModalAsync/LuiModalAsyncContext.js.map +1 -0
  14. package/dist/LuiModalAsync/LuiModalAsyncContextProvider.d.ts +54 -0
  15. package/dist/LuiModalAsync/LuiModalAsyncContextProvider.js +160 -0
  16. package/dist/LuiModalAsync/LuiModalAsyncContextProvider.js.map +1 -0
  17. package/dist/LuiModalAsync/LuiModalAsyncHeader.d.ts +15 -0
  18. package/dist/LuiModalAsync/LuiModalAsyncHeader.js +23 -0
  19. package/dist/LuiModalAsync/LuiModalAsyncHeader.js.map +1 -0
  20. package/dist/LuiModalAsync/LuiModalAsyncInstanceContext.d.ts +13 -0
  21. package/dist/LuiModalAsync/LuiModalAsyncInstanceContext.js +13 -0
  22. package/dist/LuiModalAsync/LuiModalAsyncInstanceContext.js.map +1 -0
  23. package/dist/LuiModalAsync/LuiModalAsyncMain.d.ts +5 -0
  24. package/dist/LuiModalAsync/LuiModalAsyncMain.js +6 -0
  25. package/dist/LuiModalAsync/LuiModalAsyncMain.js.map +1 -0
  26. package/dist/LuiModalAsync/index.js +12 -0
  27. package/dist/LuiModalAsync/index.js.map +1 -0
  28. package/dist/LuiModalAsync/useLuiModalPrefab.d.ts +56 -0
  29. package/dist/LuiModalAsync/useLuiModalPrefab.js +118 -0
  30. package/dist/LuiModalAsync/useLuiModalPrefab.js.map +1 -0
  31. package/dist/LuiModalAsync/useLuiModalUpload.d.ts +16 -0
  32. package/dist/LuiModalAsync/useLuiModalUpload.js +34 -0
  33. package/dist/LuiModalAsync/useLuiModalUpload.js.map +1 -0
  34. package/dist/LuiModalAsync/useShowAsyncModal.d.ts +6 -0
  35. package/dist/LuiModalAsync/useShowAsyncModal.js +13 -0
  36. package/dist/LuiModalAsync/useShowAsyncModal.js.map +1 -0
  37. package/dist/common/debug.d.ts +1 -0
  38. package/dist/common/debug.js +11 -0
  39. package/dist/common/debug.js.map +1 -0
  40. package/dist/common/index.js +3 -0
  41. package/dist/common/index.js.map +1 -0
  42. package/dist/common/useConstFunction.d.ts +5 -0
  43. package/dist/common/useConstFunction.js +17 -0
  44. package/dist/common/useConstFunction.js.map +1 -0
  45. package/dist/common/useInterval.d.ts +17 -0
  46. package/dist/common/{useInterval.ts → useInterval.js} +21 -25
  47. package/dist/common/useInterval.js.map +1 -0
  48. package/dist/common/useIsomorphicLayoutEffect.d.ts +17 -0
  49. package/dist/common/{useIsomorphicLayoutEffect.ts → useIsomorphicLayoutEffect.js} +1 -1
  50. package/dist/common/useIsomorphicLayoutEffect.js.map +1 -0
  51. package/dist/common/util.d.ts +3 -0
  52. package/dist/common/util.js +25 -0
  53. package/dist/common/util.js.map +1 -0
  54. package/dist/common/uuid.d.ts +1 -0
  55. package/dist/common/{uuid.ts → uuid.js} +1 -1
  56. package/dist/common/uuid.js.map +1 -0
  57. package/dist/components/CopyableText.d.ts +9 -0
  58. package/dist/components/CopyableText.js +29 -0
  59. package/dist/components/CopyableText.js.map +1 -0
  60. package/dist/components/index.js +2 -0
  61. package/dist/components/index.js.map +1 -0
  62. package/dist/index.js +7 -0
  63. package/dist/index.js.map +1 -0
  64. package/dist/panel/OpenPanelButton.d.ts +8 -0
  65. package/dist/panel/OpenPanelButton.js +11 -0
  66. package/dist/panel/OpenPanelButton.js.map +1 -0
  67. package/dist/panel/Panel.d.ts +10 -0
  68. package/dist/panel/Panel.js +122 -0
  69. package/dist/panel/Panel.js.map +1 -0
  70. package/dist/panel/PanelContext.d.ts +10 -0
  71. package/dist/panel/PanelContext.js +13 -0
  72. package/dist/panel/PanelContext.js.map +1 -0
  73. package/dist/panel/PanelDock.d.ts +5 -0
  74. package/dist/panel/PanelDock.js +9 -0
  75. package/dist/panel/PanelDock.js.map +1 -0
  76. package/dist/panel/PanelHeader.d.ts +15 -0
  77. package/dist/panel/PanelHeader.js +33 -0
  78. package/dist/panel/PanelHeader.js.map +1 -0
  79. package/dist/panel/PanelHeaderButton.d.ts +8 -0
  80. package/dist/panel/PanelHeaderButton.js +16 -0
  81. package/dist/panel/PanelHeaderButton.js.map +1 -0
  82. package/dist/panel/PanelInline.d.ts +10 -0
  83. package/dist/panel/PanelInline.js +26 -0
  84. package/dist/panel/PanelInline.js.map +1 -0
  85. package/dist/panel/PanelInstanceContext.d.ts +21 -0
  86. package/dist/panel/PanelInstanceContext.js +25 -0
  87. package/dist/panel/PanelInstanceContext.js.map +1 -0
  88. package/dist/panel/PanelInstanceContextProvider.d.ts +11 -0
  89. package/dist/panel/PanelInstanceContextProvider.js +50 -0
  90. package/dist/panel/PanelInstanceContextProvider.js.map +1 -0
  91. package/dist/panel/PanelsContext.d.ts +33 -0
  92. package/dist/panel/PanelsContext.js +19 -0
  93. package/dist/panel/PanelsContext.js.map +1 -0
  94. package/dist/panel/PanelsContextProvider.d.ts +12 -0
  95. package/dist/panel/PanelsContextProvider.js +145 -0
  96. package/dist/panel/PanelsContextProvider.js.map +1 -0
  97. package/dist/panel/PopinWIndow.d.ts +11 -0
  98. package/dist/panel/PopinWIndow.js +74 -0
  99. package/dist/panel/PopinWIndow.js.map +1 -0
  100. package/dist/panel/PopoutWindow.d.ts +17 -0
  101. package/dist/panel/PopoutWindow.js +72 -0
  102. package/dist/panel/PopoutWindow.js.map +1 -0
  103. package/dist/panel/generateId.d.ts +6 -0
  104. package/dist/panel/{generateId.ts → generateId.js} +3 -4
  105. package/dist/panel/generateId.js.map +1 -0
  106. package/dist/panel/handleStyleSheetsChanges.d.ts +9 -0
  107. package/dist/panel/handleStyleSheetsChanges.js +65 -0
  108. package/dist/panel/handleStyleSheetsChanges.js.map +1 -0
  109. package/dist/panel/index.js +13 -0
  110. package/dist/panel/index.js.map +1 -0
  111. package/dist/panel/openExternalWindow.d.ts +23 -0
  112. package/dist/panel/openExternalWindow.js +62 -0
  113. package/dist/panel/openExternalWindow.js.map +1 -0
  114. package/dist/panel/types/{PanelPosition.ts → PanelPosition.d.ts} +2 -2
  115. package/dist/panel/types/PanelPosition.js +2 -0
  116. package/dist/panel/types/PanelPosition.js.map +1 -0
  117. package/dist/panel/types/PanelProps.d.ts +19 -0
  118. package/dist/panel/types/PanelProps.js +2 -0
  119. package/dist/panel/types/PanelProps.js.map +1 -0
  120. package/dist/panel/types/{PanelRestoredState.ts → PanelRestoredState.d.ts} +3 -4
  121. package/dist/panel/types/PanelRestoredState.js +2 -0
  122. package/dist/panel/types/PanelRestoredState.js.map +1 -0
  123. package/dist/panel/types/PanelSize.d.ts +8 -0
  124. package/dist/panel/types/PanelSize.js +2 -0
  125. package/dist/panel/types/PanelSize.js.map +1 -0
  126. package/dist/panel/types/{PanelState.ts → PanelState.d.ts} +5 -8
  127. package/dist/panel/types/PanelState.js +2 -0
  128. package/dist/panel/types/PanelState.js.map +1 -0
  129. package/dist/panel/types/{PanelStateOptions.ts → PanelStateOptions.d.ts} +4 -6
  130. package/dist/panel/types/PanelStateOptions.js +2 -0
  131. package/dist/panel/types/PanelStateOptions.js.map +1 -0
  132. package/dist/panel/types/index.js +7 -0
  133. package/dist/panel/types/index.js.map +1 -0
  134. package/dist/panel/usePanelStateHandler.d.ts +8 -0
  135. package/dist/panel/usePanelStateHandler.js +81 -0
  136. package/dist/panel/usePanelStateHandler.js.map +1 -0
  137. package/dist/ribbon/RibbonButton.d.ts +21 -0
  138. package/dist/ribbon/RibbonButton.js +28 -0
  139. package/dist/ribbon/RibbonButton.js.map +1 -0
  140. package/dist/ribbon/RibbonButtonLink.d.ts +12 -0
  141. package/dist/ribbon/RibbonButtonLink.js +11 -0
  142. package/dist/ribbon/RibbonButtonLink.js.map +1 -0
  143. package/dist/ribbon/RibbonButtonOpenPanel.d.ts +5 -0
  144. package/dist/ribbon/RibbonButtonOpenPanel.js +11 -0
  145. package/dist/ribbon/RibbonButtonOpenPanel.js.map +1 -0
  146. package/dist/ribbon/RibbonButtonSlider.d.ts +11 -0
  147. package/dist/ribbon/RibbonButtonSlider.js +28 -0
  148. package/dist/ribbon/RibbonButtonSlider.js.map +1 -0
  149. package/dist/ribbon/RibbonButtonSliderContext.d.ts +25 -0
  150. package/dist/ribbon/RibbonButtonSliderContext.js +25 -0
  151. package/dist/ribbon/RibbonButtonSliderContext.js.map +1 -0
  152. package/dist/ribbon/RibbonContainer.d.ts +10 -0
  153. package/dist/ribbon/RibbonContainer.js +7 -0
  154. package/dist/ribbon/RibbonContainer.js.map +1 -0
  155. package/dist/ribbon/RibbonDeprecated.d.ts +10 -0
  156. package/dist/ribbon/RibbonDeprecated.js +13 -0
  157. package/dist/ribbon/RibbonDeprecated.js.map +1 -0
  158. package/dist/ribbon/RibbonMenu.d.ts +7 -0
  159. package/dist/ribbon/RibbonMenu.js +12 -0
  160. package/dist/ribbon/RibbonMenu.js.map +1 -0
  161. package/dist/ribbon/RibbonMenuOption.d.ts +17 -0
  162. package/dist/ribbon/RibbonMenuOption.js +26 -0
  163. package/dist/ribbon/RibbonMenuOption.js.map +1 -0
  164. package/dist/ribbon/RibbonMenuSeparator.d.ts +2 -0
  165. package/dist/ribbon/RibbonMenuSeparator.js +6 -0
  166. package/dist/ribbon/RibbonMenuSeparator.js.map +1 -0
  167. package/dist/ribbon/RibbonSeparator.d.ts +2 -0
  168. package/dist/ribbon/RibbonSeparator.js +4 -0
  169. package/dist/ribbon/RibbonSeparator.js.map +1 -0
  170. package/dist/ribbon/index.js +12 -0
  171. package/dist/ribbon/index.js.map +1 -0
  172. package/package.json +14 -8
  173. package/dist/LuiModalAsync/LuiModalAsync.tsx +0 -82
  174. package/dist/LuiModalAsync/LuiModalAsyncButtonGroup.tsx +0 -55
  175. package/dist/LuiModalAsync/LuiModalAsyncContent.tsx +0 -9
  176. package/dist/LuiModalAsync/LuiModalAsyncContext.tsx +0 -52
  177. package/dist/LuiModalAsync/LuiModalAsyncContextProvider.tsx +0 -223
  178. package/dist/LuiModalAsync/LuiModalAsyncHeader.tsx +0 -67
  179. package/dist/LuiModalAsync/LuiModalAsyncInstanceContext.ts +0 -24
  180. package/dist/LuiModalAsync/LuiModalAsyncMain.tsx +0 -8
  181. package/dist/LuiModalAsync/useLuiModalPrefab.tsx +0 -227
  182. package/dist/LuiModalAsync/useLuiModalUpload.tsx +0 -79
  183. package/dist/LuiModalAsync/useShowAsyncModal.ts +0 -34
  184. package/dist/common/debug.ts +0 -9
  185. package/dist/common/useConstFunction.ts +0 -22
  186. package/dist/common/util.ts +0 -31
  187. package/dist/components/CopyableText.tsx +0 -58
  188. package/dist/panel/OpenPanelButton.tsx +0 -52
  189. package/dist/panel/Panel.tsx +0 -211
  190. package/dist/panel/PanelContext.ts +0 -22
  191. package/dist/panel/PanelDock.tsx +0 -20
  192. package/dist/panel/PanelHeader.tsx +0 -105
  193. package/dist/panel/PanelHeaderButton.tsx +0 -26
  194. package/dist/panel/PanelInline.tsx +0 -46
  195. package/dist/panel/PanelInstanceContext.ts +0 -44
  196. package/dist/panel/PanelInstanceContextProvider.tsx +0 -75
  197. package/dist/panel/PanelsContext.tsx +0 -56
  198. package/dist/panel/PanelsContextProvider.tsx +0 -220
  199. package/dist/panel/PopinWIndow.tsx +0 -147
  200. package/dist/panel/PopoutWindow.tsx +0 -117
  201. package/dist/panel/handleStyleSheetsChanges.ts +0 -71
  202. package/dist/panel/openExternalWindow.ts +0 -98
  203. package/dist/panel/types/PanelProps.ts +0 -22
  204. package/dist/panel/types/PanelSize.ts +0 -9
  205. package/dist/panel/usePanelStateHandler.tsx +0 -102
  206. package/dist/ribbon/RibbonButton.tsx +0 -112
  207. package/dist/ribbon/RibbonButtonLink.tsx +0 -27
  208. package/dist/ribbon/RibbonButtonOpenPanel.tsx +0 -23
  209. package/dist/ribbon/RibbonButtonSlider.tsx +0 -66
  210. package/dist/ribbon/RibbonButtonSliderContext.tsx +0 -34
  211. package/dist/ribbon/RibbonContainer.tsx +0 -19
  212. package/dist/ribbon/RibbonDeprecated.tsx +0 -27
  213. package/dist/ribbon/RibbonMenu.tsx +0 -25
  214. package/dist/ribbon/RibbonMenuOption.tsx +0 -67
  215. package/dist/ribbon/RibbonMenuSeparator.tsx +0 -5
  216. package/dist/ribbon/RibbonSeparator.tsx +0 -3
  217. /package/dist/LuiModalAsync/{index.ts → index.d.ts} +0 -0
  218. /package/dist/common/{index.ts → index.d.ts} +0 -0
  219. /package/dist/components/{index.ts → index.d.ts} +0 -0
  220. /package/dist/{index.ts → index.d.ts} +0 -0
  221. /package/dist/panel/{index.ts → index.d.ts} +0 -0
  222. /package/dist/panel/types/{index.ts → index.d.ts} +0 -0
  223. /package/dist/ribbon/{index.ts → index.d.ts} +0 -0
package/package.json CHANGED
@@ -12,8 +12,15 @@
12
12
  "panel",
13
13
  "popout"
14
14
  ],
15
- "main": "./dist/index.ts",
16
- "version": "10.3.1",
15
+ "main": "./dist/index.js",
16
+ "types": "./dist/index.d.ts",
17
+ "exports": {
18
+ ".": {
19
+ "types": "./dist/index.d.ts",
20
+ "import": "./dist/index.js"
21
+ }
22
+ },
23
+ "version": "11.0.0",
17
24
  "peerDependencies": {
18
25
  "@linzjs/lui": ">=23",
19
26
  "react": ">=18",
@@ -33,7 +40,7 @@
33
40
  "build": "node -e \"require('fs').mkdirSync('./dist',{recursive:true})\" && npm run clean && npm run lintall && npm run bundle",
34
41
  "yalc": "npm run clean && npm run bundle && yalc push",
35
42
  "clean": "node -e \"fs.rmSync('dist', { recursive: true, force: true })\"",
36
- "bundle": "tsc --noEmit && rollup -c",
43
+ "bundle": "tsc && rollup -c",
37
44
  "test": "vitest run",
38
45
  "test:watch": "vitest --watch",
39
46
  "lintall": "npm run lint:style && npm run lint:oxlint",
@@ -73,11 +80,11 @@
73
80
  "ag-grid-community": "34.2.0",
74
81
  "ag-grid-react": "34.2.0",
75
82
  "jsdom": "^27.3.0",
76
- "oxfmt": "^0.48.0",
77
- "oxlint": "^1.63.0",
83
+ "oxfmt": "^0.50.0",
84
+ "oxlint": "^1.65.0",
78
85
  "react": "^18.3.1",
79
86
  "react-dom": "18.3.1",
80
- "rollup": "^4.60.3",
87
+ "rollup": "^4.60.4",
81
88
  "rollup-plugin-copy": "^3.5.0",
82
89
  "sass": "^1.99.0",
83
90
  "storybook": "10.3.6",
@@ -87,8 +94,7 @@
87
94
  "stylelint-config-standard": "^39.0.1",
88
95
  "stylelint-scss": "6.14.0",
89
96
  "typescript": "^5.9.3",
90
- "vite": "^7.3.2",
91
- "vite-tsconfig-paths": "^5.1.4",
97
+ "vite": "^8.0.13",
92
98
  "vitest": "^4.1.5"
93
99
  },
94
100
  "browserslist": {
@@ -1,82 +0,0 @@
1
- import '../index.scss';
2
-
3
- import clsx from 'clsx';
4
- import { delay } from 'lodash-es';
5
- import React, { CSSProperties, PropsWithChildren, ReactElement, useContext, useEffect, useRef } from 'react';
6
-
7
- import { LuiModalAsyncInstanceContext } from './LuiModalAsyncInstanceContext';
8
-
9
- export interface LuiModalAsyncProps {
10
- className?: string;
11
- style?: CSSProperties;
12
- /**
13
- * Close on clicking overlay
14
- */
15
- closeOnOverlayClick?: boolean;
16
- }
17
-
18
- /**
19
- * This creates the dialog element.
20
- */
21
- export const LuiModalAsync = ({
22
- style,
23
- className,
24
- closeOnOverlayClick,
25
- children,
26
- }: PropsWithChildren<LuiModalAsyncProps>): ReactElement => {
27
- const dialogRef = useRef<HTMLDialogElement>(null);
28
-
29
- const { close } = useContext(LuiModalAsyncInstanceContext);
30
-
31
- // The only way to create a modal dialog is to call showModal, open attribute will not work
32
- useEffect(() => {
33
- // Check if it's open already to support .vite hot deploys
34
- if (!dialogRef.current?.open) {
35
- dialogRef.current?.showModal?.();
36
- }
37
- }, []);
38
-
39
- useEffect(() => {
40
- // Dialogs auto select the first focusable element, this is in case you don't want that
41
- // For example we don't want to select the help button by default, so we add data-noautofocus
42
- delay(() => {
43
- const d = dialogRef.current;
44
- if (!d) {
45
- return;
46
- }
47
- const input = (d.querySelectorAll('[data-autofocus]')[0] ??
48
- d.querySelectorAll('[type=file]')[0] ??
49
- d.querySelectorAll('button:not([data-noautofocus]),input:not([data-noautofocus])')[0]) as
50
- | HTMLElement
51
- | undefined;
52
-
53
- if (input) {
54
- input.focus?.();
55
- if ('select' in input) {
56
- (input as HTMLInputElement).select?.();
57
- }
58
- }
59
- }, 100);
60
- }, []);
61
-
62
- // You cannot override dialogs position from absolute.
63
- return className?.includes('storybook') ? (
64
- <div className={clsx('LuiModalAsync', className)} style={style}>
65
- {children}
66
- </div>
67
- ) : (
68
- <dialog
69
- role={'dialog'}
70
- className={clsx('LuiModalAsync', className)}
71
- style={style}
72
- ref={dialogRef}
73
- onCancel={(e) => {
74
- e.preventDefault();
75
- close();
76
- }}
77
- onClick={(e) => closeOnOverlayClick && e.target === e.currentTarget && close()}
78
- >
79
- {children}
80
- </dialog>
81
- );
82
- };
@@ -1,55 +0,0 @@
1
- import { LuiButton } from '@linzjs/lui';
2
- import { LuiButtonProps } from '@linzjs/lui/dist/components/LuiButton/LuiButton';
3
- import React, { PropsWithChildren, useContext } from 'react';
4
-
5
- import { LuiModalAsyncInstanceContext } from './LuiModalAsyncInstanceContext';
6
-
7
- /**
8
- * Wrapper for buttons at the bottom of model.
9
- */
10
- export const LuiModalAsyncButtonGroup = ({ children }: PropsWithChildren<unknown>) => (
11
- <div className={'LuiModalAsync-ButtonGroup'}>{children}</div>
12
- );
13
-
14
- /**
15
- * Calls model close on click.
16
- */
17
- export const LuiModalAsyncButtonDismiss = React.forwardRef<HTMLButtonElement, LuiButtonProps & { autofocus?: boolean }>(
18
- function LuiModalAsyncButtonDismiss(props, ref) {
19
- return (
20
- <LuiButton
21
- {...props}
22
- {...(props.level ? {} : { level: 'tertiary' })}
23
- {...(props.autofocus ? { buttonProps: { 'data-autofocus': true } } : {})}
24
- ref={ref}
25
- onClick={useContext(LuiModalAsyncInstanceContext).close}
26
- >
27
- {props.children}
28
- </LuiButton>
29
- );
30
- },
31
- );
32
-
33
- /**
34
- * Resolves to value on click, or if onClick is specified calls onClick.
35
- */
36
- export const LuiModalAsyncButtonContinue = React.forwardRef<
37
- HTMLButtonElement,
38
- LuiButtonProps & { value?: unknown; autofocus?: boolean }
39
- >(function LuiModalAsyncButtonContinue(props, ref) {
40
- const { resolve } = useContext(LuiModalAsyncInstanceContext);
41
- return (
42
- <LuiButton
43
- {...props}
44
- {...(props.level ? {} : { level: 'primary' })}
45
- {...(props.autofocus ? { buttonProps: { 'data-autofocus': true } } : {})}
46
- ref={ref}
47
- onClick={(e) => {
48
- if (props.onClick) props.onClick(e);
49
- else resolve(props.value ?? 'continue');
50
- }}
51
- >
52
- {props.children}
53
- </LuiButton>
54
- );
55
- });
@@ -1,9 +0,0 @@
1
- import React, { PropsWithChildren } from 'react';
2
-
3
- /**
4
- * Wrapper for modal content.
5
- * Content is the scrollable area.
6
- */
7
- export const LuiModalAsyncContent = ({ children }: PropsWithChildren<unknown>) => (
8
- <div className={'LuiModalAsync-content'}>{children}</div>
9
- );
@@ -1,52 +0,0 @@
1
- import { ComponentProps, createContext, createRef, MutableRefObject, ReactElement } from 'react';
2
-
3
- export const openModalOnAllWindows = createRef<HTMLDivElement>();
4
-
5
- /**
6
- * @param showOnAllWindows If true this modal will show on all windows opened from main window including main window.
7
- * @param
8
- */
9
- export interface ShowModalProps {
10
- showOnAllWindows?: boolean;
11
- polledCloseCondition?: () => boolean;
12
- }
13
-
14
- // eslint-disable-next-line
15
- export type ComponentType = (props: any) => ReactElement;
16
-
17
- /**
18
- * Promise extended to add the ability to externally resolve dialog.
19
- */
20
- export interface PromiseWithResolve<RT> extends Promise<RT> {
21
- resolve: (value: RT) => void;
22
- }
23
-
24
- /**
25
- * Properties passed to the modal component to allow resolving.
26
- */
27
- export interface LuiModalAsyncCallback<R> {
28
- resolve: (result: R | undefined) => void;
29
- close: () => void;
30
- }
31
-
32
- export interface LuiModalAsyncContextType {
33
- showModal: <
34
- OR extends HTMLElement | null,
35
- // eslint-disable-next-line
36
- PROPS extends LuiModalAsyncCallback<any>,
37
- CT extends (props: PROPS) => ReactElement,
38
- RT = Parameters<ComponentProps<CT>['resolve']>[0],
39
- >(
40
- ownerRef: MutableRefObject<OR>,
41
- component: CT,
42
- args: Omit<ComponentProps<CT>, 'resolve' | 'close'>,
43
- showModalProps?: ShowModalProps,
44
- ) => PromiseWithResolve<RT>;
45
- }
46
-
47
- export const LuiModalAsyncContext = createContext<LuiModalAsyncContextType>({
48
- // eslint-disable-next-line @typescript-eslint/require-await
49
- showModal: (async () => {
50
- console.error('Missing LuiModalAsyncContext Provider');
51
- }) as unknown as LuiModalAsyncContextType['showModal'],
52
- });
@@ -1,223 +0,0 @@
1
- import React, {
2
- MutableRefObject,
3
- PropsWithChildren,
4
- ReactElement,
5
- useCallback,
6
- useEffect,
7
- useRef,
8
- useState,
9
- } from 'react';
10
- import { createPortal } from 'react-dom';
11
-
12
- import { debugLog } from '../common/debug';
13
- import {
14
- ComponentType,
15
- LuiModalAsyncContext,
16
- openModalOnAllWindows,
17
- PromiseWithResolve,
18
- ShowModalProps,
19
- } from './LuiModalAsyncContext';
20
- import { LuiModalAsyncInstanceContext } from './LuiModalAsyncInstanceContext';
21
- import { useInterval } from '../common/useInterval';
22
- import { v4 } from '../common/uuid';
23
-
24
- export interface LuiModalAsyncInstance {
25
- uuid: string;
26
- ownerRef: MutableRefObject<HTMLElement | null>;
27
- componentInstance: ReactElement;
28
- // eslint-disable-next-line
29
- resolve: (result: any) => void;
30
- showModalProps?: ShowModalProps;
31
- }
32
-
33
- /**
34
- * Provides the ability to show modals using react components without needing useState boilerplate and inline dialogs.
35
- *
36
- * To use:
37
- * <ol>
38
- * <li>Add this Provider somewhere in your standard providers
39
- * <pre>
40
- * <LuiModalAsyncContextProvider>
41
- * ...children
42
- * </LuiModalAsyncContextProvider>
43
- * </pre>
44
- * </li>
45
- * <li>Add the modal return type to the element as below, and use the props resolve/close from ModalProps for results.
46
- * <pre>
47
- * export interface SomeModalProps extends ModalProps<number> {
48
- * someProp?: number; // user props
49
- * }
50
- *
51
- * export const SomeModal = ({initialState, resolve, close}: SomeModalProps): ReactElement => {
52
- * return Modal(
53
- * <div>
54
- * Itsa me, I'm a modal
55
- * <button onClick={close}>Cancel</button>
56
- * <button onClick={()=>resolve(someProp)}>Save</button>
57
- * </div>
58
- * )}
59
- * }
60
- * </pre>
61
- * </li>
62
- * <li> To show the dialog and get the result...
63
- * <pre>
64
- * // Note: modalOwnerRef is only required if you need to support popout windows
65
- * const { showModal, modalOwnerRef } = useShowAsyncModal();
66
- * ...
67
- * const showModal = () => {
68
- * const result = await showModal(SomeModal, { someProp: 1 });
69
- * if (!result) return; // modal cancelled
70
- * }
71
- *
72
- * return <button onClick={showModal} ref={modalOwnerRef}>Show Modal!</button>
73
- * </pre>
74
- * </li>
75
- * </ol>
76
- */
77
- export const LuiModalAsyncContextProvider = ({ children }: PropsWithChildren<unknown>): ReactElement => {
78
- const [modals, setModals] = useState<LuiModalAsyncInstance[]>([]);
79
- const openWindowsRef = useRef([window]);
80
-
81
- // hook window open for opening dialogs across multiple windows
82
- useEffect(() => {
83
- const oldWindowOpen = window.open;
84
- window.open = (...props) => {
85
- const r = oldWindowOpen(...props);
86
- // We don't want to track non app-windows, e.g. help screens
87
- if (!props[0]) {
88
- if (r) {
89
- openWindowsRef.current.push(r as typeof window);
90
- }
91
- }
92
- return r;
93
- };
94
-
95
- return () => {
96
- window.open = oldWindowOpen;
97
- };
98
- }, []);
99
-
100
- /**
101
- * Inserts the modal into the page, and removes once modal has a result.
102
- * Note: full generic types are provided by the interface. Function def has been simplified here.
103
- *
104
- * @param ownerRef Reference to element that opened this dialog such that it works for popout windows.
105
- * @param Component React component.
106
- * @param args Arguments for react component.
107
- */
108
- const showModal = useCallback(
109
- (
110
- ownerRef: MutableRefObject<HTMLElement | null>,
111
- Component: ComponentType,
112
- // eslint-disable-next-line
113
- args: any,
114
- showModalProps?: ShowModalProps,
115
- ): // eslint-disable-next-line
116
- PromiseWithResolve<any> => {
117
- if (!('level' in args)) {
118
- debugLog(`Show generic modal`, args);
119
- }
120
- const uuid = v4();
121
- // eslint-disable-next-line
122
- let extResolve: PromiseWithResolve<any>['resolve'];
123
-
124
- // @ts-expect-error promise resolve cast
125
- // eslint-disable-next-line
126
- const promise: PromiseWithResolve<any> = new Promise((resolve) => {
127
- extResolve = resolve;
128
- try {
129
- // If there are any exceptions the modal won't show
130
- setModals((modals) => [
131
- ...modals,
132
- {
133
- uuid,
134
- ownerRef,
135
- // eslint-disable-next-line
136
- componentInstance: <Component {...args} resolve={resolve} close={() => resolve(undefined)} />,
137
- resolve,
138
- showModalProps,
139
- },
140
- ]);
141
- } catch (e) {
142
- console.error(e);
143
- return;
144
- }
145
- }).then((result) => {
146
- debugLog('Modal resolved result =', JSON.stringify(result));
147
- return new Promise((resolve) => {
148
- // Close modal
149
- setModals((modals) => {
150
- // Defer resolving to give react a chance to update the view allowing the async event model to run.
151
- // Just in case the task following this is long-running with non IO code, which will block the event queue.
152
- setTimeout(() => resolve(result), 10);
153
- return modals.filter((e) => e.uuid !== uuid);
154
- });
155
- });
156
- });
157
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
158
- promise.resolve = extResolve!;
159
- return promise;
160
- },
161
- [],
162
- );
163
-
164
- /**
165
- * Check modal is still attached to a window.
166
- */
167
- const modalHasView = useCallback(
168
- (modalInstance: LuiModalAsyncInstance): boolean =>
169
- modalInstance.ownerRef === openModalOnAllWindows || !!modalInstance.ownerRef.current?.ownerDocument.defaultView,
170
- [],
171
- );
172
-
173
- const windowIsOpen = useCallback((w: typeof window): boolean => !w.closed, []);
174
-
175
- /**
176
- * Tidy up modals that have closed because of an external window closing
177
- */
178
- useInterval(() => {
179
- const newModals = modals.filter(modalHasView);
180
- if (newModals.length !== modals.length) {
181
- setModals(newModals);
182
- }
183
- // We could do this with window close listeners, but they are unreliable
184
- openWindowsRef.current = openWindowsRef.current.filter((w) => !w.closed);
185
-
186
- newModals.forEach((modalInstance) => {
187
- if (modalInstance.showModalProps?.polledCloseCondition?.()) {
188
- modalInstance.resolve(undefined);
189
- }
190
- });
191
- }, 500);
192
-
193
- const portalOwners = (modalInstance: LuiModalAsyncInstance) =>
194
- modalInstance.ownerRef == openModalOnAllWindows
195
- ? openWindowsRef.current.filter(windowIsOpen).map((frame) => frame.document.body)
196
- : [(modalInstance.ownerRef.current?.ownerDocument ?? document).body];
197
-
198
- return (
199
- <LuiModalAsyncContext.Provider
200
- value={{
201
- showModal,
202
- }}
203
- >
204
- <>
205
- {modals.filter(modalHasView).map((modalInstance) => (
206
- <LuiModalAsyncInstanceContext.Provider
207
- key={modalInstance.uuid}
208
- value={{
209
- ownerRef: modalInstance.ownerRef,
210
- close: () => modalInstance.resolve(undefined),
211
- resolve: modalInstance.resolve,
212
- }}
213
- >
214
- {portalOwners(modalInstance).map((element) =>
215
- createPortal(<>{modalInstance.componentInstance}</>, element),
216
- )}
217
- </LuiModalAsyncInstanceContext.Provider>
218
- ))}
219
- </>
220
- <>{children}</>
221
- </LuiModalAsyncContext.Provider>
222
- );
223
- };
@@ -1,67 +0,0 @@
1
- import '../index.scss';
2
-
3
- import { LuiButton, LuiIcon } from '@linzjs/lui';
4
- import { LuiIconName } from '@linzjs/lui/dist/assets/svg-content';
5
- import React, { PropsWithChildren, ReactElement, useContext } from 'react';
6
-
7
- import { PanelHeaderButton } from '../panel';
8
- import { LuiModalAsyncInstanceContext } from './LuiModalAsyncInstanceContext';
9
-
10
- export interface LuiModalAsyncHeaderProps {
11
- icon?: LuiIconName | ReactElement | null;
12
- title: string;
13
- closeButton?: true;
14
- helpLink?: string;
15
- onHelpClick?: () => void;
16
- // @Deprecated This has no effect. Don't use it
17
- helpButtonLevel?: 'text' | 'plain-text' | 'primary' | 'secondary' | 'tertiary' | 'success' | 'error';
18
- }
19
-
20
- /**
21
- * Generic modal header.
22
- */
23
- export const LuiModalAsyncHeader = ({
24
- icon,
25
- title,
26
- closeButton,
27
- helpLink,
28
- onHelpClick,
29
- helpButtonLevel,
30
- }: PropsWithChildren<LuiModalAsyncHeaderProps>) => {
31
- const { ownerRef, close } = useContext(LuiModalAsyncInstanceContext);
32
-
33
- return (
34
- <div className={'LuiModalAsync-header'}>
35
- {icon &&
36
- (typeof icon === 'string' ? (
37
- <LuiIcon
38
- name={icon}
39
- alt={'icon'}
40
- size={'md'}
41
- className={`LuiModalAsync-header-icon LuiModalAsync-header-icon-${icon}`}
42
- />
43
- ) : (
44
- icon
45
- ))}
46
- <h4>{title}</h4>
47
- {(helpLink || onHelpClick) && (
48
- <LuiButton
49
- type={'button'}
50
- level={helpButtonLevel || 'plain-text'}
51
- aria-label={'Help'}
52
- title={'Help'}
53
- className={'lui-button-icon-only'}
54
- buttonProps={{ 'data-noautofocus': true }}
55
- onClick={
56
- helpLink
57
- ? () => (ownerRef.current?.ownerDocument?.defaultView ?? window).open(helpLink, '_blank')
58
- : onHelpClick
59
- }
60
- >
61
- <LuiIcon name="ic_help_outline" alt="Help" size="md" className={'LuiModalAsync-help-icon'} />
62
- </LuiButton>
63
- )}
64
- {closeButton && <PanelHeaderButton aria-label={'Close'} onClick={close} icon={'ic_clear'} />}
65
- </div>
66
- );
67
- };
@@ -1,24 +0,0 @@
1
- import { createContext, MutableRefObject } from 'react';
2
-
3
- /**
4
- * Actions that can be taken from within the modal via instance context
5
- */
6
- export interface LuiModalAsyncInstanceContextType {
7
- ownerRef: MutableRefObject<HTMLElement | null>;
8
- close: () => void;
9
- // eslint-disable-next-line
10
- resolve: (value: any) => void;
11
- }
12
-
13
- const NoContextError = () => {
14
- console.error('Missing LuiModalAsyncInstanceContext Provider');
15
- };
16
-
17
- /**
18
- * Provides access to resolving/closing to modal elements.
19
- */
20
- export const LuiModalAsyncInstanceContext = createContext<LuiModalAsyncInstanceContextType>({
21
- ownerRef: { current: null },
22
- close: NoContextError,
23
- resolve: NoContextError,
24
- });
@@ -1,8 +0,0 @@
1
- import React, { PropsWithChildren } from 'react';
2
-
3
- /**
4
- * Wraps the content and header. This is just to match the way figma is arranged.
5
- */
6
- export const LuiModalAsyncMain = ({ children }: PropsWithChildren<unknown>) => (
7
- <div className={'LuiModalAsync-main'}>{children}</div>
8
- );