@driveflux/ui 1.0.0-next.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 (108) hide show
  1. package/.eslintrc.json +3 -0
  2. package/.swcrc +14 -0
  3. package/.turbo/turbo-build.log +6 -0
  4. package/CHANGELOG.md +12 -0
  5. package/dist/chakra.d.ts +2 -0
  6. package/dist/chakra.d.ts.map +1 -0
  7. package/dist/chakra.js +1 -0
  8. package/dist/cjs/chakra.js +18 -0
  9. package/dist/cjs/index.js +18 -0
  10. package/dist/cjs/modal/ModalProvider.js +254 -0
  11. package/dist/cjs/modal/components/EnhancedModalCustomWrapper.js +139 -0
  12. package/dist/cjs/modal/components/EnhancedModalFooter.js +167 -0
  13. package/dist/cjs/modal/components/MinimalModalContent.js +94 -0
  14. package/dist/cjs/modal/components/StandardModalContent.js +387 -0
  15. package/dist/cjs/modal/context.js +20 -0
  16. package/dist/cjs/modal/index.js +48 -0
  17. package/dist/cjs/modal/use-enhanced-modal.js +15 -0
  18. package/dist/cjs/package.json +3 -0
  19. package/dist/cjs/theme/colors.js +140 -0
  20. package/dist/cjs/theme/index.js +18 -0
  21. package/dist/cjs/toast/index.js +19 -0
  22. package/dist/cjs/toast/use-toast-result.js +255 -0
  23. package/dist/cjs/types.js +4 -0
  24. package/dist/cjs/utils/accessors.js +61 -0
  25. package/dist/cjs/utils/index.js +19 -0
  26. package/dist/cjs/utils/react.js +94 -0
  27. package/dist/index.d.ts +2 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +1 -0
  30. package/dist/modal/ModalProvider.d.ts +4 -0
  31. package/dist/modal/ModalProvider.d.ts.map +1 -0
  32. package/dist/modal/ModalProvider.js +239 -0
  33. package/dist/modal/components/EnhancedModalCustomWrapper.d.ts +9 -0
  34. package/dist/modal/components/EnhancedModalCustomWrapper.d.ts.map +1 -0
  35. package/dist/modal/components/EnhancedModalCustomWrapper.js +124 -0
  36. package/dist/modal/components/EnhancedModalFooter.d.ts +12 -0
  37. package/dist/modal/components/EnhancedModalFooter.d.ts.map +1 -0
  38. package/dist/modal/components/EnhancedModalFooter.js +157 -0
  39. package/dist/modal/components/MinimalModalContent.d.ts +11 -0
  40. package/dist/modal/components/MinimalModalContent.d.ts.map +1 -0
  41. package/dist/modal/components/MinimalModalContent.js +84 -0
  42. package/dist/modal/components/StandardModalContent.d.ts +11 -0
  43. package/dist/modal/components/StandardModalContent.d.ts.map +1 -0
  44. package/dist/modal/components/StandardModalContent.js +377 -0
  45. package/dist/modal/context.d.ts +62 -0
  46. package/dist/modal/context.d.ts.map +1 -0
  47. package/dist/modal/context.js +10 -0
  48. package/dist/modal/index.d.ts +7 -0
  49. package/dist/modal/index.d.ts.map +1 -0
  50. package/dist/modal/index.js +6 -0
  51. package/dist/modal/use-enhanced-modal.d.ts +3 -0
  52. package/dist/modal/use-enhanced-modal.d.ts.map +1 -0
  53. package/dist/modal/use-enhanced-modal.js +5 -0
  54. package/dist/theme/colors.d.ts +148 -0
  55. package/dist/theme/colors.d.ts.map +1 -0
  56. package/dist/theme/colors.js +130 -0
  57. package/dist/theme/index.d.ts +2 -0
  58. package/dist/theme/index.d.ts.map +1 -0
  59. package/dist/theme/index.js +1 -0
  60. package/dist/toast/index.d.ts +2 -0
  61. package/dist/toast/index.d.ts.map +1 -0
  62. package/dist/toast/index.js +1 -0
  63. package/dist/toast/use-toast-result.d.ts +30 -0
  64. package/dist/toast/use-toast-result.d.ts.map +1 -0
  65. package/dist/toast/use-toast-result.js +232 -0
  66. package/dist/types.d.ts +5 -0
  67. package/dist/types.d.ts.map +1 -0
  68. package/dist/types.js +1 -0
  69. package/dist/utils/accessors.d.ts +24 -0
  70. package/dist/utils/accessors.d.ts.map +1 -0
  71. package/dist/utils/accessors.js +28 -0
  72. package/dist/utils/index.d.ts +3 -0
  73. package/dist/utils/index.d.ts.map +1 -0
  74. package/dist/utils/index.js +2 -0
  75. package/dist/utils/react.d.ts +5 -0
  76. package/dist/utils/react.d.ts.map +1 -0
  77. package/dist/utils/react.js +32 -0
  78. package/index.cjs +1 -0
  79. package/index.d.ts +1 -0
  80. package/modal.cjs +1 -0
  81. package/modal.d.ts +1 -0
  82. package/package.json +68 -0
  83. package/src/chakra.ts +1 -0
  84. package/src/index.ts +1 -0
  85. package/src/modal/ModalProvider.tsx +142 -0
  86. package/src/modal/components/EnhancedModalCustomWrapper.tsx +39 -0
  87. package/src/modal/components/EnhancedModalFooter.tsx +51 -0
  88. package/src/modal/components/MinimalModalContent.tsx +24 -0
  89. package/src/modal/components/StandardModalContent.tsx +65 -0
  90. package/src/modal/context.tsx +81 -0
  91. package/src/modal/index.ts +7 -0
  92. package/src/modal/use-enhanced-modal.ts +7 -0
  93. package/src/theme/colors.ts +171 -0
  94. package/src/theme/index.ts +1 -0
  95. package/src/toast/index.ts +3 -0
  96. package/src/toast/use-toast-result.tsx +169 -0
  97. package/src/types.ts +22 -0
  98. package/src/utils/accessors.ts +64 -0
  99. package/src/utils/index.ts +2 -0
  100. package/src/utils/react.ts +32 -0
  101. package/theme.cjs +1 -0
  102. package/theme.d.ts +1 -0
  103. package/toast.cjs +1 -0
  104. package/toast.d.ts +1 -0
  105. package/tsconfig.json +14 -0
  106. package/tsconfig.tsbuildinfo +1 -0
  107. package/utils.cjs +1 -0
  108. package/utils.d.ts +1 -0
@@ -0,0 +1,169 @@
1
+ import type { Problem, ValidationIssues } from '@driveflux/problem'
2
+ import type { StandardResult } from '@driveflux/result'
3
+ import { t } from '@lingui/macro'
4
+ import merge from 'lodash/merge.js'
5
+ import { useCallback } from 'react'
6
+ import {
7
+ Box,
8
+ ListItem,
9
+ Text,
10
+ UnorderedList,
11
+ useToast,
12
+ type CreateToastFnReturn,
13
+ type ToastId,
14
+ type UseToastOptions
15
+ } from '../chakra.js'
16
+ import { accessReactNode, type ReactNodeAccessor } from '../utils/accessors.js'
17
+
18
+ export type StatusFn<T> = (data?: T) => UseToastOptions['status']
19
+
20
+ const accessStatus = <D,>(s?: UseToastOptions['status'] | StatusFn<D>, data?: D): UseToastOptions['status'] => {
21
+ return typeof s === 'function' ? s(data) : s
22
+ }
23
+
24
+ type CustomUseToastOptions<T> = Omit<UseToastOptions, 'status' | 'title' | 'description'> & {
25
+ status?: UseToastOptions['status'] | StatusFn<T>
26
+ title?: UseToastOptions['title'] | ReactNodeAccessor<T>
27
+ description?: UseToastOptions['description'] | ReactNodeAccessor<T>
28
+ }
29
+
30
+ type ErrorUseToastOptions<E = Problem> = CustomUseToastOptions<E> & {
31
+ showValidationErrors?: boolean
32
+ defaultDescription?: string
33
+ }
34
+
35
+ type UseToastResultOptions<S = any | Problem, E = Problem> = {
36
+ defaultOptions?: CustomUseToastOptions<S>
37
+ success?: CustomUseToastOptions<S> | boolean | null
38
+ error?: ErrorUseToastOptions<E> | boolean | null
39
+ }
40
+
41
+ type UseToastResult = {
42
+ toastProblem: <P extends Problem>(problem: P, providedOptions?: ErrorUseToastOptions<P>) => ToastId
43
+ toastSuccess: <T extends any>(providedOptions?: CustomUseToastOptions<T>) => ToastId
44
+ toastResult: <T extends unknown, R extends StandardResult<T> = StandardResult<T>>(
45
+ result: R,
46
+ generalToastOptions?: UseToastResultOptions<T, Problem>
47
+ ) => ToastId | undefined
48
+ toastError: (providedOptions?: UseToastOptions) => ToastId
49
+ toast: CreateToastFnReturn
50
+ }
51
+
52
+ const defaultUseToastResultOptions = {
53
+ success: {
54
+ status: 'success',
55
+ title: t`Success`,
56
+ description: t`The operation was done successfully`,
57
+ isClosable: true
58
+ },
59
+ error: {
60
+ status: 'error',
61
+ title: t`Operation Failed`,
62
+ defaultDescription: t`There was a problem while performing this operation`,
63
+ showValidationErrors: true,
64
+ isClosable: true
65
+ }
66
+ } as const satisfies UseToastResultOptions
67
+
68
+ export const getValidationErrorsList = (validation: ValidationIssues) => {
69
+ return Object.values(validation.fieldErrors)
70
+ .map((v) => v.map((vd) => vd.message))
71
+ .flat()
72
+ }
73
+
74
+ const accessOptions = <S,>(options?: CustomUseToastOptions<S>, data?: S): UseToastOptions | undefined => {
75
+ if (!options) {
76
+ return options
77
+ }
78
+
79
+ return {
80
+ ...options,
81
+ status: accessStatus(options.status, data),
82
+ title: accessReactNode(options.title, data),
83
+ description: accessReactNode(options.description, data)
84
+ }
85
+ }
86
+
87
+ export const useToastResult = (options?: UseToastResultOptions): UseToastResult => {
88
+ const originalToast = useToast(accessOptions(options?.defaultOptions))
89
+
90
+ const toastProblem: UseToastResult['toastProblem'] = useCallback(
91
+ (problem, providedOptions) => {
92
+ const { description, defaultDescription, showValidationErrors, ...rest } = merge(
93
+ {},
94
+ defaultUseToastResultOptions.error,
95
+ providedOptions
96
+ )
97
+ const problemMessage = problem.message || defaultDescription
98
+ return originalToast({
99
+ ...accessOptions(rest, problem),
100
+ description: accessReactNode(description, problem) || (
101
+ <Box>
102
+ <>
103
+ {problemMessage && <Text color={'inherit'}>{problemMessage}</Text>}
104
+ {problem.validation && showValidationErrors && (
105
+ <UnorderedList color={'inherit'}>
106
+ {getValidationErrorsList(problem.validation).map((message, i) => (
107
+ <ListItem key={i}>{message}</ListItem>
108
+ ))}
109
+ </UnorderedList>
110
+ )}
111
+ </>
112
+ </Box>
113
+ )
114
+ })
115
+ },
116
+ [originalToast]
117
+ )
118
+
119
+ const toastError: UseToastResult['toastError'] = useCallback(
120
+ (providedOptions) => {
121
+ const options = accessOptions(merge({}, defaultUseToastResultOptions.error, providedOptions))
122
+ return originalToast({
123
+ ...options
124
+ })
125
+ },
126
+ [originalToast]
127
+ )
128
+
129
+ const toastSuccess: UseToastResult['toastSuccess'] = useCallback(
130
+ (providedOptions) => {
131
+ const options = accessOptions(merge({}, defaultUseToastResultOptions.success, providedOptions))
132
+ return originalToast({
133
+ ...options
134
+ })
135
+ },
136
+ [originalToast]
137
+ )
138
+
139
+ const toastResult: UseToastResult['toastResult'] = useCallback(
140
+ (result, generalToastOptions) => {
141
+ const options = merge({}, defaultUseToastResultOptions, generalToastOptions || defaultUseToastResultOptions)
142
+ const toastType = result.ok ? 'success' : 'error'
143
+ const toastOptions =
144
+ typeof generalToastOptions === 'undefined' || generalToastOptions[toastType] === null
145
+ ? null
146
+ : options[toastType]
147
+ if (!toastOptions) {
148
+ return
149
+ }
150
+
151
+ const finalToastOptions = {
152
+ ...(accessOptions(
153
+ typeof toastOptions === 'boolean' ? defaultUseToastResultOptions[toastType] : toastOptions,
154
+ result.val
155
+ ) as UseToastOptions | ErrorUseToastOptions)
156
+ } as UseToastOptions | ErrorUseToastOptions
157
+ return result.ok ? toastSuccess(finalToastOptions) : toastProblem(result.val, finalToastOptions)
158
+ },
159
+ [originalToast, toastProblem, toastSuccess]
160
+ )
161
+
162
+ return {
163
+ toastProblem,
164
+ toastSuccess,
165
+ toastResult,
166
+ toastError,
167
+ toast: originalToast
168
+ }
169
+ }
package/src/types.ts ADDED
@@ -0,0 +1,22 @@
1
+ export type LengthUnits =
2
+ | 'cm'
3
+ | 'mm'
4
+ | 'in'
5
+ | 'px'
6
+ | 'pt'
7
+ | 'pc'
8
+ | 'em'
9
+ | 'ex'
10
+ | 'ch'
11
+ | 'vw'
12
+ | 'vh'
13
+ | 'rem'
14
+ | 'vmin'
15
+ | 'vmax'
16
+ | '%'
17
+
18
+ export type StyleUnit = number | `${number}${LengthUnits}`
19
+
20
+ export type Sizes = 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 'xs' | '3xl' | '4xl' | '5xl' | '6xl' | 'full'
21
+
22
+ export type Padding = 'base' | 'md'
@@ -0,0 +1,64 @@
1
+ import type { ReactNode } from 'react'
2
+
3
+ type AllowedParam = string | number | boolean | Date | undefined | null
4
+ type AllowedQueryParams = Record<string, AllowedParam | AllowedParam[]>
5
+
6
+ export type GenericAccessor<O, R> = (m: O) => R
7
+
8
+ export type SelfAccessor<O, R = any> = GenericAccessor<O, R>
9
+ export type StringAccessor<O, R extends string = string> = GenericAccessor<O, R>
10
+ export type StringOrNullAccessor<O, R extends string = string> = GenericAccessor<O, R | null>
11
+ export type SelfPartialAccessor<O> = GenericAccessor<O, Partial<O>>
12
+ export type QueryAccessor<O, R extends AllowedQueryParams = AllowedQueryParams> = GenericAccessor<O, R>
13
+ export type ReactNodeAccessor<O> = GenericAccessor<O, ReactNode>
14
+ export type BooleanAccessor<O> = GenericAccessor<O, boolean>
15
+ export interface FunctionAccessor<O, F extends (...args: any[]) => any> { generateFunction: GenericAccessor<O, F> }
16
+
17
+ export type GuaranteedAccessor<AC extends (...args: any[]) => any> = (
18
+ arg1: Required<Parameters<AC>>[0],
19
+ arg2?: Parameters<AC>[1],
20
+ arg3?: Parameters<AC>[2],
21
+ arg4?: Parameters<AC>[3],
22
+ arg5?: Parameters<AC>[4]
23
+ ) => ReturnType<AC>
24
+
25
+ export const accessSelf = <D, S, DS = S>(s: S, data?: D, defaultValue?: DS) => {
26
+ if (!s) {
27
+ return defaultValue
28
+ }
29
+
30
+ return typeof s === 'function' ? s(data) : s
31
+ }
32
+
33
+ export const accessBoolean = <D>(s: boolean | BooleanAccessor<D>, data?: D, defaultBoolean?: boolean) =>
34
+ accessSelf(s, data, defaultBoolean)
35
+
36
+ export const accessString = <D>(s: string | StringAccessor<D>, data?: D, defaultText?: string) =>
37
+ accessSelf(s, data, defaultText)
38
+
39
+ export const accessStringOrNull = <D>(
40
+ s: string | null | StringOrNullAccessor<D>,
41
+ data?: D,
42
+ defaultText: string | null = null
43
+ ) => accessSelf(s, data, defaultText)
44
+
45
+ export const accessQuery = <D>(
46
+ s: AllowedQueryParams | QueryAccessor<D>,
47
+ data?: D,
48
+ defaultQuery?: AllowedQueryParams
49
+ ) => accessSelf(s, data, defaultQuery)
50
+
51
+ export const accessReactNode = <D>(s: ReactNode | ReactNodeAccessor<D>, data?: D, defaultNode?: ReactNode) =>
52
+ accessSelf(s, data, defaultNode)
53
+
54
+ export const accessFunction = <D, F extends (...args: any[]) => any>(
55
+ f: FunctionAccessor<D, F> | F,
56
+ data?: D,
57
+ defaultFunction?: F
58
+ ) => {
59
+ if (!f) {
60
+ return defaultFunction
61
+ }
62
+
63
+ return typeof f === 'object' && 'generateFunction' in f ? f.generateFunction(data as D) : f
64
+ }
@@ -0,0 +1,2 @@
1
+ export * from './accessors.js'
2
+ export * from './react.js'
@@ -0,0 +1,32 @@
1
+ import { default as React, isValidElement } from 'react'
2
+
3
+ export function isReactComponent(Component: any): Component is React.ComponentType<any> {
4
+ return (
5
+ typeof Component === 'function' &&
6
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- React component, it's fine
7
+ (Component.prototype instanceof React.Component || Component.displayName !== undefined)
8
+ )
9
+ }
10
+
11
+ export function isReactElement(element: any): element is React.ReactElement {
12
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument -- isValidElement is a validation function
13
+ return isValidElement(element)
14
+ }
15
+
16
+ export function isReactNode(node: any): node is React.ReactNode {
17
+ if (
18
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument -- isValidElement is a validation function
19
+ isValidElement(node) || // Check if it's a React element
20
+ typeof node === 'string' || // Check if it's a string
21
+ typeof node === 'number' // Check if it's a number
22
+ ) {
23
+ return true
24
+ }
25
+
26
+ // Check if it's an array of React nodes
27
+ if (Array.isArray(node) && node.every((element) => isReactNode(element))) {
28
+ return true
29
+ }
30
+
31
+ return false
32
+ }
package/theme.cjs ADDED
@@ -0,0 +1 @@
1
+ module.exports = require('./dist/cjs/theme/index.js')
package/theme.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './dist/theme/index'
package/toast.cjs ADDED
@@ -0,0 +1 @@
1
+ module.exports = require('./dist/cjs/toast/index.js')
package/toast.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './dist/toast/index'
package/tsconfig.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/tsconfig",
3
+ "extends": "@driveflux/tsconfig/nextjs.json",
4
+ "compilerOptions": {
5
+ "declaration": true,
6
+ "rootDir": "src",
7
+ "outDir": "./dist"
8
+ },
9
+ "include": [
10
+ "src/**/*.ts",
11
+ "src/**/*.tsx"
12
+ ],
13
+ "exclude": ["node_modules"]
14
+ }