@simplysm/solid 13.0.97 → 13.0.98
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.
- package/README.md +349 -0
- package/docs/data.md +216 -0
- package/docs/disclosure.md +164 -0
- package/docs/display.md +94 -0
- package/docs/features.md +279 -0
- package/docs/feedback.md +210 -0
- package/docs/form-control.md +537 -0
- package/docs/helpers.md +168 -0
- package/docs/hooks.md +143 -0
- package/docs/layout.md +182 -0
- package/docs/providers.md +177 -0
- package/docs/styles.md +127 -0
- package/package.json +5 -5
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# Disclosure Components
|
|
2
|
+
|
|
3
|
+
Source: `src/components/disclosure/**/*.tsx`
|
|
4
|
+
|
|
5
|
+
## Collapse
|
|
6
|
+
|
|
7
|
+
Animated expand/collapse container using margin-top transition.
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
interface CollapseProps extends JSX.HTMLAttributes<HTMLDivElement> {
|
|
11
|
+
open?: boolean; // default: false
|
|
12
|
+
}
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
- Uses `ResizeObserver` to track content height.
|
|
16
|
+
- Disables transition on initial render to prevent flicker.
|
|
17
|
+
- Sets `visibility: hidden` when closed to prevent focusable element access.
|
|
18
|
+
|
|
19
|
+
## Dropdown
|
|
20
|
+
|
|
21
|
+
Positioned popup with trigger element. Uses Portal for rendering.
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
interface DropdownProps {
|
|
25
|
+
position?: { x: number; y: number }; // absolute position (for context menus)
|
|
26
|
+
open?: boolean;
|
|
27
|
+
onOpenChange?: (open: boolean) => void;
|
|
28
|
+
maxHeight?: number; // default: 300
|
|
29
|
+
disabled?: boolean;
|
|
30
|
+
keyboardNav?: boolean; // arrow key navigation
|
|
31
|
+
class?: string;
|
|
32
|
+
style?: JSX.CSSProperties;
|
|
33
|
+
children: JSX.Element;
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
- Auto-positions above or below trigger based on available viewport space.
|
|
38
|
+
- Closes on outside click, Escape key, scroll, and resize.
|
|
39
|
+
- `keyboardNav`: ArrowDown/Up navigates between tabbable items in popup.
|
|
40
|
+
|
|
41
|
+
### Sub-components
|
|
42
|
+
|
|
43
|
+
- **`Dropdown.Trigger`** -- Click target that toggles the dropdown. Slot component.
|
|
44
|
+
- **`Dropdown.Content`** -- Popup content. Slot component.
|
|
45
|
+
|
|
46
|
+
## Dialog
|
|
47
|
+
|
|
48
|
+
Modal or floating dialog with drag, resize, z-index management, and animation.
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
interface DialogProps {
|
|
52
|
+
open?: boolean;
|
|
53
|
+
onOpenChange?: (open: boolean) => void;
|
|
54
|
+
withCloseButton?: boolean; // default: true
|
|
55
|
+
closeOnInteractOutside?: boolean; // default: false (uses DialogDefaults)
|
|
56
|
+
closeOnEscape?: boolean; // default: true (uses DialogDefaults)
|
|
57
|
+
resizable?: boolean; // default: false
|
|
58
|
+
draggable?: boolean; // default: true
|
|
59
|
+
mode?: "float" | "fill";
|
|
60
|
+
width?: number;
|
|
61
|
+
height?: number;
|
|
62
|
+
minWidth?: number;
|
|
63
|
+
minHeight?: number;
|
|
64
|
+
position?: "bottom-right" | "top-right";
|
|
65
|
+
headerStyle?: JSX.CSSProperties | string;
|
|
66
|
+
beforeClose?: () => boolean; // return false to prevent close
|
|
67
|
+
onCloseComplete?: () => void;
|
|
68
|
+
class?: string;
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
- `mode="float"`: no backdrop, pointer-events pass through.
|
|
73
|
+
- `mode="fill"`: full-screen dialog.
|
|
74
|
+
- 8-direction resize handles when `resizable=true`.
|
|
75
|
+
- Automatic z-index stacking across multiple open dialogs.
|
|
76
|
+
|
|
77
|
+
### Sub-components
|
|
78
|
+
|
|
79
|
+
- **`Dialog.Header`** -- Dialog title bar. Enables drag when `draggable=true`.
|
|
80
|
+
- **`Dialog.Action`** -- Action buttons rendered in the header next to the close button.
|
|
81
|
+
|
|
82
|
+
## DialogProvider
|
|
83
|
+
|
|
84
|
+
Programmatic dialog provider. Enables `useDialog().show()` to open dialogs as Promises.
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
interface DialogProviderProps extends DialogDefaults {}
|
|
88
|
+
|
|
89
|
+
interface DialogDefaults {
|
|
90
|
+
closeOnEscape?: boolean;
|
|
91
|
+
closeOnInteractOutside?: boolean;
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### useDialog()
|
|
96
|
+
|
|
97
|
+
Hook to open dialogs programmatically.
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
function useDialog(): DialogContextValue;
|
|
101
|
+
|
|
102
|
+
interface DialogContextValue {
|
|
103
|
+
show<P extends Record<string, any>>(
|
|
104
|
+
component: Component<P>,
|
|
105
|
+
props: Omit<P, "close">,
|
|
106
|
+
options?: DialogShowOptions,
|
|
107
|
+
): Promise<ExtractCloseResult<P> | undefined>;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
interface DialogShowOptions {
|
|
111
|
+
header?: JSX.Element;
|
|
112
|
+
withCloseButton?: boolean;
|
|
113
|
+
closeOnInteractOutside?: boolean;
|
|
114
|
+
closeOnEscape?: boolean;
|
|
115
|
+
resizable?: boolean;
|
|
116
|
+
draggable?: boolean;
|
|
117
|
+
mode?: "float" | "fill";
|
|
118
|
+
width?: number;
|
|
119
|
+
height?: number;
|
|
120
|
+
minWidth?: number;
|
|
121
|
+
minHeight?: number;
|
|
122
|
+
position?: "bottom-right" | "top-right";
|
|
123
|
+
headerStyle?: JSX.CSSProperties | string;
|
|
124
|
+
beforeClose?: () => boolean;
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
The dialog component receives a `close` prop. Call `close(result)` to resolve the Promise.
|
|
129
|
+
|
|
130
|
+
### DialogDefaultsContext
|
|
131
|
+
|
|
132
|
+
Context providing default dialog configuration. Used by `Dialog` when per-instance props are not set.
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
const DialogDefaultsContext: Context<Accessor<DialogDefaults>>;
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Tabs
|
|
139
|
+
|
|
140
|
+
Tab bar with value-based selection.
|
|
141
|
+
|
|
142
|
+
```ts
|
|
143
|
+
interface TabsProps {
|
|
144
|
+
value?: string;
|
|
145
|
+
onValueChange?: (value: string) => void;
|
|
146
|
+
size?: ComponentSize;
|
|
147
|
+
class?: string;
|
|
148
|
+
style?: JSX.CSSProperties;
|
|
149
|
+
children?: JSX.Element;
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Sub-components
|
|
154
|
+
|
|
155
|
+
- **`Tabs.Tab`** -- Individual tab button.
|
|
156
|
+
|
|
157
|
+
```ts
|
|
158
|
+
interface TabsTabProps {
|
|
159
|
+
value: string;
|
|
160
|
+
disabled?: boolean;
|
|
161
|
+
class?: string;
|
|
162
|
+
children?: JSX.Element;
|
|
163
|
+
}
|
|
164
|
+
```
|
package/docs/display.md
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Display Components
|
|
2
|
+
|
|
3
|
+
Source: `src/components/display/**/*.tsx`
|
|
4
|
+
|
|
5
|
+
## Barcode
|
|
6
|
+
|
|
7
|
+
SVG barcode renderer powered by bwip-js.
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
interface BarcodeProps extends JSX.HTMLAttributes<HTMLDivElement> {
|
|
11
|
+
type: BarcodeType;
|
|
12
|
+
value?: string;
|
|
13
|
+
}
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
### BarcodeType
|
|
17
|
+
|
|
18
|
+
Union type of all supported barcode formats. Common values include: `"qrcode"`, `"code128"`, `"ean13"`, `"datamatrix"`, `"pdf417"`, `"azteccode"`, `"code39"`, `"upca"`, `"isbn"`.
|
|
19
|
+
|
|
20
|
+
Full list exported from `src/components/display/Barcode.types.ts` with 100+ formats.
|
|
21
|
+
|
|
22
|
+
## Card
|
|
23
|
+
|
|
24
|
+
Elevated container with shadow and fade-in animation.
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
interface CardProps extends JSX.HTMLAttributes<HTMLDivElement> {}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Applies surface background, rounded corners, shadow with hover/focus-within elevation.
|
|
31
|
+
|
|
32
|
+
## Echarts
|
|
33
|
+
|
|
34
|
+
Apache ECharts wrapper with reactive option updates and resize handling.
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
interface EchartsProps extends JSX.HTMLAttributes<HTMLDivElement> {
|
|
38
|
+
option: echarts.EChartsOption;
|
|
39
|
+
busy?: boolean; // shows/hides loading indicator
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
- Uses SVG renderer.
|
|
44
|
+
- Automatically resizes with container via `ResizeObserver`.
|
|
45
|
+
|
|
46
|
+
## Icon
|
|
47
|
+
|
|
48
|
+
Tabler icon wrapper using `Dynamic` rendering.
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
interface IconProps extends Omit<TablerIconProps, "size"> {
|
|
52
|
+
icon: Component<TablerIconProps>;
|
|
53
|
+
size?: string | number; // default: "1.25em"
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Adds `inline` display and vertical alignment.
|
|
58
|
+
|
|
59
|
+
## Tag
|
|
60
|
+
|
|
61
|
+
Themed inline tag/badge with solid background.
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
type TagTheme = SemanticTheme;
|
|
65
|
+
|
|
66
|
+
interface TagProps extends JSX.HTMLAttributes<HTMLSpanElement> {
|
|
67
|
+
theme?: TagTheme; // default: "base"
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Link
|
|
72
|
+
|
|
73
|
+
Themed anchor link with hover underline.
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
type LinkTheme = SemanticTheme;
|
|
77
|
+
|
|
78
|
+
interface LinkProps extends JSX.AnchorHTMLAttributes<HTMLAnchorElement> {
|
|
79
|
+
theme?: LinkTheme; // default: "primary"
|
|
80
|
+
disabled?: boolean;
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Alert
|
|
85
|
+
|
|
86
|
+
Themed alert/callout box with light background.
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
type AlertTheme = SemanticTheme;
|
|
90
|
+
|
|
91
|
+
interface AlertProps extends JSX.HTMLAttributes<HTMLDivElement> {
|
|
92
|
+
theme?: AlertTheme; // default: "base"
|
|
93
|
+
}
|
|
94
|
+
```
|
package/docs/features.md
ADDED
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
# Feature Components
|
|
2
|
+
|
|
3
|
+
Source: `src/components/features/**/*.tsx`
|
|
4
|
+
|
|
5
|
+
## AddressSearchContent
|
|
6
|
+
|
|
7
|
+
Korean address search component using Daum Postcode API.
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
interface AddressSearchResult {
|
|
11
|
+
postNumber: string | undefined;
|
|
12
|
+
address: string | undefined;
|
|
13
|
+
buildingName: string | undefined;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const AddressSearchContent: Component<{
|
|
17
|
+
close?: (result?: AddressSearchResult) => void;
|
|
18
|
+
}>;
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Designed for use with `useDialog().show()`. Loads the Daum Postcode script on mount.
|
|
22
|
+
|
|
23
|
+
## SharedDataSelect
|
|
24
|
+
|
|
25
|
+
Select component bound to a shared data definition. Supports single and multiple modes with the same prop variants as `Select`.
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
type SharedDataSelectProps<TItem, TDataKey extends string> = {
|
|
29
|
+
dataKey: TDataKey;
|
|
30
|
+
// ...inherits Select props (value, onValueChange, multiple, etc.)
|
|
31
|
+
// plus shared data specific:
|
|
32
|
+
getItemSearchText?: (item: TItem) => string;
|
|
33
|
+
isItemHidden?: (item: TItem) => boolean;
|
|
34
|
+
};
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Sub-components
|
|
38
|
+
|
|
39
|
+
- **`SharedDataSelect.ItemTemplate`** -- Render template for items.
|
|
40
|
+
|
|
41
|
+
## SharedDataSelectButton
|
|
42
|
+
|
|
43
|
+
Button that opens a shared data selection dialog.
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
type SharedDataSelectButtonProps<TItem, TDataKey extends string> = {
|
|
47
|
+
dataKey: TDataKey;
|
|
48
|
+
value?: TItem | TItem[];
|
|
49
|
+
onValueChange?: (value: TItem | TItem[] | undefined) => void;
|
|
50
|
+
renderValue?: (value: TItem) => JSX.Element;
|
|
51
|
+
// ...plus button/validation props
|
|
52
|
+
};
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## SharedDataSelectList
|
|
56
|
+
|
|
57
|
+
List component bound to shared data, rendering items from a shared data definition.
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
interface SharedDataSelectListProps<TItem> {
|
|
61
|
+
dataKey: string;
|
|
62
|
+
value?: unknown[];
|
|
63
|
+
onValueChange?: (value: unknown[]) => void;
|
|
64
|
+
// ...list configuration props
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Sub-components
|
|
69
|
+
|
|
70
|
+
- **`SharedDataSelectList.ItemTemplate`** -- Render template for list items.
|
|
71
|
+
|
|
72
|
+
## DataSelectButton
|
|
73
|
+
|
|
74
|
+
Button that opens a custom data selection dialog. Generic over key type and dialog props.
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
interface DataSelectButtonProps<TKey, TDialogProps> {
|
|
78
|
+
value?: TKey | TKey[];
|
|
79
|
+
onValueChange?: (value: TKey | TKey[] | undefined) => void;
|
|
80
|
+
renderValue?: (value: TKey) => JSX.Element;
|
|
81
|
+
dialog: Component<TDialogProps>;
|
|
82
|
+
dialogProps?: Omit<TDialogProps, "close">;
|
|
83
|
+
multiple?: boolean;
|
|
84
|
+
disabled?: boolean;
|
|
85
|
+
required?: boolean;
|
|
86
|
+
size?: ComponentSize;
|
|
87
|
+
inset?: boolean;
|
|
88
|
+
class?: string;
|
|
89
|
+
style?: JSX.CSSProperties;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
interface DataSelectDialogResult<TKey> {
|
|
93
|
+
selectedKeys: TKey[];
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
interface SelectDialogBaseProps<TKey> {
|
|
97
|
+
close?: (result?: DataSelectDialogResult<TKey>) => void;
|
|
98
|
+
initialSelectedKeys?: TKey[];
|
|
99
|
+
selectionMode?: "single" | "multiple";
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## CrudSheet
|
|
104
|
+
|
|
105
|
+
Full-featured CRUD data grid combining DataSheet with search, pagination, sorting, inline/dialog editing, selection, and Excel import/export.
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
type CrudSheetProps<TItem, TFilter extends Record<string, unknown>> = {
|
|
109
|
+
search: (filter: TFilter, page: number | undefined, sorts: SortingDef[]) => Promise<SearchResult<TItem>>;
|
|
110
|
+
getItemKey: (item: TItem) => string | number | undefined;
|
|
111
|
+
storageKey?: string;
|
|
112
|
+
editable?: boolean;
|
|
113
|
+
isItemEditable?: (item: TItem) => boolean;
|
|
114
|
+
isItemDeletable?: (item: TItem) => boolean;
|
|
115
|
+
isItemDeleted?: (item: TItem) => boolean;
|
|
116
|
+
isItemSelectable?: (item: TItem) => boolean | string;
|
|
117
|
+
lastModifiedAtProp?: string;
|
|
118
|
+
lastModifiedByProp?: string;
|
|
119
|
+
filterInitial?: TFilter;
|
|
120
|
+
items?: TItem[];
|
|
121
|
+
onItemsChange?: (items: TItem[]) => void;
|
|
122
|
+
excel?: ExcelConfig<TItem>;
|
|
123
|
+
selectionMode?: "single" | "multiple";
|
|
124
|
+
selectedKeys?: (string | number)[];
|
|
125
|
+
onSelectedKeysChange?: (keys: (string | number)[]) => void;
|
|
126
|
+
onSelect?: (result: SelectResult<TItem>) => void;
|
|
127
|
+
onSubmitComplete?: () => void;
|
|
128
|
+
hideAutoTools?: boolean;
|
|
129
|
+
close?: () => void;
|
|
130
|
+
class?: string;
|
|
131
|
+
children: JSX.Element;
|
|
132
|
+
} & (
|
|
133
|
+
| { inlineEdit: InlineEditConfig<TItem>; dialogEdit?: never }
|
|
134
|
+
| { dialogEdit: DialogEditConfig<TItem>; inlineEdit?: never }
|
|
135
|
+
| { inlineEdit?: never; dialogEdit?: never }
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
interface SearchResult<TItem> {
|
|
139
|
+
items: TItem[];
|
|
140
|
+
pageCount?: number;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
interface InlineEditConfig<TItem> {
|
|
144
|
+
submit: (diffs: ArrayOneWayDiffResult<TItem>[]) => Promise<void>;
|
|
145
|
+
newItem: () => TItem;
|
|
146
|
+
deleteProp?: keyof TItem & string;
|
|
147
|
+
diffsExcludes?: string[];
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
interface DialogEditConfig<TItem> {
|
|
151
|
+
editItem: (item?: TItem) => Promise<boolean | undefined>;
|
|
152
|
+
deleteItems?: (items: TItem[]) => Promise<boolean>;
|
|
153
|
+
restoreItems?: (items: TItem[]) => Promise<boolean>;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
interface ExcelConfig<TItem> {
|
|
157
|
+
download: (items: TItem[]) => Promise<void>;
|
|
158
|
+
upload?: (file: File) => Promise<void>;
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Sub-components
|
|
163
|
+
|
|
164
|
+
- **`CrudSheet.Column<TItem>`** -- Column definition with cell context.
|
|
165
|
+
|
|
166
|
+
```ts
|
|
167
|
+
interface CrudSheetColumnProps<TItem> extends Omit<DataSheetColumnProps<TItem>, "children"> {
|
|
168
|
+
editTrigger?: boolean;
|
|
169
|
+
children: (ctx: CrudSheetCellContext<TItem>) => JSX.Element;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
interface CrudSheetCellContext<TItem> {
|
|
173
|
+
item: TItem;
|
|
174
|
+
index: number;
|
|
175
|
+
row: number;
|
|
176
|
+
depth: number;
|
|
177
|
+
setItem: <TKey extends keyof TItem>(key: TKey, value: TItem[TKey]) => void;
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
- **`CrudSheet.Filter<TFilter>`** -- Filter panel slot.
|
|
182
|
+
|
|
183
|
+
```ts
|
|
184
|
+
interface CrudSheetFilterSlotProps<TFilter> {
|
|
185
|
+
filter: TFilter;
|
|
186
|
+
setFilter: SetStoreFunction<TFilter>;
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
- **`CrudSheet.Tools<TItem>`** -- Toolbar slot with context.
|
|
191
|
+
|
|
192
|
+
```ts
|
|
193
|
+
interface CrudSheetToolsSlotProps<TItem> {
|
|
194
|
+
ctx: CrudSheetContext<TItem>;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
interface CrudSheetContext<TItem> {
|
|
198
|
+
items(): TItem[];
|
|
199
|
+
selection(): TItem[];
|
|
200
|
+
page(): number;
|
|
201
|
+
sorts(): SortingDef[];
|
|
202
|
+
busy(): boolean;
|
|
203
|
+
hasChanges(): boolean;
|
|
204
|
+
save(): Promise<void>;
|
|
205
|
+
refresh(): Promise<void>;
|
|
206
|
+
addItem(): void;
|
|
207
|
+
clearSelection(): void;
|
|
208
|
+
setPage(page: number): void;
|
|
209
|
+
setSorts(sorts: SortingDef[]): void;
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## CrudDetail
|
|
214
|
+
|
|
215
|
+
CRUD detail form with load, save, delete, and change tracking.
|
|
216
|
+
|
|
217
|
+
```ts
|
|
218
|
+
interface CrudDetailProps<TData extends object> {
|
|
219
|
+
load: () => Promise<{ data: TData; info: CrudDetailInfo }>;
|
|
220
|
+
children: (ctx: CrudDetailContext<TData>) => JSX.Element;
|
|
221
|
+
submit?: (data: TData) => Promise<boolean | undefined>;
|
|
222
|
+
toggleDelete?: (del: boolean) => Promise<boolean | undefined>;
|
|
223
|
+
editable?: boolean;
|
|
224
|
+
deletable?: boolean;
|
|
225
|
+
data?: TData;
|
|
226
|
+
onDataChange?: (data: TData) => void;
|
|
227
|
+
close?: (result?: boolean) => void;
|
|
228
|
+
class?: string;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
interface CrudDetailInfo {
|
|
232
|
+
isNew: boolean;
|
|
233
|
+
isDeleted: boolean;
|
|
234
|
+
lastModifiedAt?: DateTime;
|
|
235
|
+
lastModifiedBy?: string;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
interface CrudDetailContext<TData> {
|
|
239
|
+
data: TData;
|
|
240
|
+
setData: SetStoreFunction<TData>;
|
|
241
|
+
info: () => CrudDetailInfo;
|
|
242
|
+
busy: () => boolean;
|
|
243
|
+
hasChanges: () => boolean;
|
|
244
|
+
save: () => Promise<void>;
|
|
245
|
+
refresh: () => Promise<void>;
|
|
246
|
+
}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### Sub-components
|
|
250
|
+
|
|
251
|
+
- **`CrudDetail.Header`** -- Header content slot.
|
|
252
|
+
|
|
253
|
+
## PermissionTable
|
|
254
|
+
|
|
255
|
+
Permission matrix table displaying app permissions with checkboxes.
|
|
256
|
+
|
|
257
|
+
```ts
|
|
258
|
+
interface PermissionTableProps<TModule = string> {
|
|
259
|
+
perms: AppPerm<TModule>[];
|
|
260
|
+
value?: string[];
|
|
261
|
+
onValueChange?: (value: string[]) => void;
|
|
262
|
+
disabled?: boolean;
|
|
263
|
+
class?: string;
|
|
264
|
+
style?: JSX.CSSProperties;
|
|
265
|
+
}
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### Helper Functions
|
|
269
|
+
|
|
270
|
+
```ts
|
|
271
|
+
function collectAllPerms<TModule>(items: AppPerm<TModule>[]): string[];
|
|
272
|
+
function filterByModules<TModule>(items: AppPerm<TModule>[], enabledModules: TModule[]): AppPerm<TModule>[];
|
|
273
|
+
function changePermCheck<TModule>(
|
|
274
|
+
items: AppPerm<TModule>[],
|
|
275
|
+
currentPerms: string[],
|
|
276
|
+
changedPerm: string,
|
|
277
|
+
checked: boolean,
|
|
278
|
+
): string[];
|
|
279
|
+
```
|