@fewbox/den-web 0.2.0-preview.4 → 0.2.0-preview.41
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/engine.js +2 -0
- package/engine.js.map +1 -0
- package/{index-constants.d.ts → index-engine.d.ts} +15 -22
- package/index.css +1 -1
- package/index.js +1 -1
- package/index.js.map +1 -1
- package/package.json +6 -8
- package/scripts/generate-packages.js +5 -8
- package/server.js +71 -0
- package/src/components/Engine/Base/index.d.ts +3 -3
- package/src/components/Engine/index.d.ts +21 -14
- package/src/components/Layout/Dock/DockPopoverOverlay/index.d.ts +13 -0
- package/src/components/Layout/Dock/DockPortalOverlay/index.d.ts +11 -0
- package/src/components/Layout/Dock/index.d.ts +8 -26
- package/src/components/Layout/Dock/types.d.ts +39 -0
- package/src/components/View/VAside/index.d.ts +5 -0
- package/src/components/View/VErrorBoundary/index.d.ts +1 -1
- package/src/components/View/VForm/index.d.ts +1 -0
- package/src/components/View/VInput/VDropdown/index.d.ts +15 -1
- package/src/components/View/VInput/VFile/index.d.ts +2 -1
- package/src/components/View/VNav/index.d.ts +5 -0
- package/src/components/View/VTextArea/index.d.ts +1 -4
- package/src/components/View/VTooltip/index.d.ts +2 -5
- package/src/components/View/VTree/Block/index.d.ts +1 -1
- package/src/components/View/VTree/index.d.ts +2 -6
- package/src/components/View/VTree/types.d.ts +6 -0
- package/src/components/core.d.ts +3 -1
- package/templates/.claude/skills/fewbox-den/SKILL.md +471 -434
- package/templates/FEWBOX.md +12 -35
- package/templates/style/_core.scss +12 -0
- package/templates/style/_root-properties.scss +4 -1
- package/templates/style/_variables.scss +13 -1
- package/tsconfig.app.tsbuildinfo +1 -1
- package/constants.js +0 -2
- package/constants.js.map +0 -1
- package/src/components/View/VDynamic/index.d.ts +0 -7
- package/src/components/app.d.ts +0 -21
- package/src/fewbox/index.d.ts +0 -42
- package/src/language/index.d.ts +0 -13
- package/src/network/FormHeaders.d.ts +0 -4
- package/src/network/IGraphQL.d.ts +0 -6
- package/src/network/JsonHeaders.d.ts +0 -5
- package/src/network/Network.d.ts +0 -45
- package/src/network/NetworkObservableBase.d.ts +0 -14
- package/src/network/StreamObservableBase.d.ts +0 -11
- package/src/network/UploadHeaders.d.ts +0 -4
- package/src/network/WS.d.ts +0 -11
- package/src/network/ajax/default/Delete.d.ts +0 -5
- package/src/network/ajax/default/DeleteText.d.ts +0 -5
- package/src/network/ajax/default/Get.d.ts +0 -5
- package/src/network/ajax/default/GetLocal.d.ts +0 -5
- package/src/network/ajax/default/GetText.d.ts +0 -5
- package/src/network/ajax/default/NetworkObservableAjax.d.ts +0 -7
- package/src/network/ajax/default/Patch.d.ts +0 -5
- package/src/network/ajax/default/PatchText.d.ts +0 -5
- package/src/network/ajax/default/Post.d.ts +0 -5
- package/src/network/ajax/default/PostText.d.ts +0 -5
- package/src/network/ajax/default/Put.d.ts +0 -5
- package/src/network/ajax/default/PutText.d.ts +0 -5
- package/src/network/ajax/external/DeleteExternal.d.ts +0 -5
- package/src/network/ajax/external/DeleteTextExternal.d.ts +0 -5
- package/src/network/ajax/external/GetExternal.d.ts +0 -5
- package/src/network/ajax/external/GetTextExternal.d.ts +0 -5
- package/src/network/ajax/external/NetworkObservableAjaxExternal.d.ts +0 -8
- package/src/network/ajax/external/PatchExternal.d.ts +0 -5
- package/src/network/ajax/external/PatchTextExternal.d.ts +0 -5
- package/src/network/ajax/external/PostExternal.d.ts +0 -5
- package/src/network/ajax/external/PostTextExternal.d.ts +0 -5
- package/src/network/ajax/external/PutExternal.d.ts +0 -5
- package/src/network/ajax/external/PutTextExternal.d.ts +0 -5
- package/src/network/fetch/default/DeleteFetch.d.ts +0 -5
- package/src/network/fetch/default/GetFetch.d.ts +0 -5
- package/src/network/fetch/default/NetworkObservableFetch.d.ts +0 -7
- package/src/network/fetch/default/PatchFetch.d.ts +0 -5
- package/src/network/fetch/default/PostFetch.d.ts +0 -5
- package/src/network/fetch/default/PutFetch.d.ts +0 -5
- package/src/network/fetch/external/DeleteFetchExternal.d.ts +0 -5
- package/src/network/fetch/external/GetFetchExternal.d.ts +0 -5
- package/src/network/fetch/external/NetworkObservableFetchExternal.d.ts +0 -8
- package/src/network/fetch/external/PatchFetchExternal.d.ts +0 -5
- package/src/network/fetch/external/PostFetchExternal.d.ts +0 -5
- package/src/network/fetch/external/PutFetchExternal.d.ts +0 -5
- package/src/network/graphql/default/GQL.d.ts +0 -6
- package/src/network/graphql/default/GQLUpload.d.ts +0 -5
- package/src/network/graphql/default/NetworkObservableGQL.d.ts +0 -7
- package/src/network/graphql/external/GQLExternal.d.ts +0 -6
- package/src/network/graphql/external/GQLExternalUpload.d.ts +0 -6
- package/src/network/graphql/external/NetworkObservableGQLExternal.d.ts +0 -7
- package/src/network/index.d.ts +0 -50
- package/src/network/sse/default/GetSSE.d.ts +0 -5
- package/src/network/sse/default/PostSSE.d.ts +0 -5
- package/src/network/sse/default/StreamObservableSSE.d.ts +0 -5
- package/src/network/sse/external/GetSSEExternal.d.ts +0 -5
- package/src/network/sse/external/PostSSEExternal.d.ts +0 -5
- package/src/network/sse/external/StreamObservableSSEExternal.d.ts +0 -6
- package/src/network/util.d.ts +0 -5
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: fewbox-den
|
|
3
|
-
description: Use when writing React UI with the fewbox-den component library. Provides component API reference for layouts (X/Y/S series), views (VLabel, VForm, VInput, etc.), network clients (Fetch, SSE, GraphQL, WebSocket), styling (ColorType, FontSizeType), and common patterns (page layout, forms, cards). Invoke this skill when you see
|
|
3
|
+
description: Use when writing React UI with the fewbox-den component library. Provides component API reference for layouts (X/Y/S series), views (VLabel, VForm, VInput, etc.), network clients (Fetch, SSE, GraphQL, WebSocket), styling (ColorType, FontSizeType), and common patterns (page layout, forms, cards). Invoke this skill when you see fewbox-den imports or need to create UI with fewbox-den.
|
|
4
4
|
allowed-tools: Read, Grep, Glob
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -10,26 +10,21 @@ When writing code that uses fewbox-den, follow the patterns and API documented b
|
|
|
10
10
|
|
|
11
11
|
## Import Pattern
|
|
12
12
|
|
|
13
|
-
All components
|
|
13
|
+
All components, enums, and types are named exports:
|
|
14
14
|
|
|
15
15
|
```tsx
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
|
|
20
|
-
// Components accessed via:
|
|
21
|
-
Den.Components.XCenter
|
|
22
|
-
Den.Components.VLabel
|
|
23
|
-
Den.Components.ColorType // enums are also under Components
|
|
16
|
+
import { XCenter, VLabel, ColorType } from '@fewbox/den'; // core variant
|
|
17
|
+
import { XCenter, VLabel, GetFetch, boot } from '@fewbox/den-app'; // app variant (includes network/store)
|
|
18
|
+
import { XCenter, VLabel, Debug } from '@fewbox/den-web'; // web variant
|
|
24
19
|
```
|
|
25
20
|
|
|
26
21
|
### Variant Exports
|
|
27
22
|
|
|
28
|
-
- **core** (`
|
|
29
|
-
- **web** (`
|
|
30
|
-
- **app** (`
|
|
31
|
-
- **app** also exports:
|
|
32
|
-
- **append** (no
|
|
23
|
+
- **core** (`@fewbox/den`): Layout (X/Y/S/Flex/FlexItem/Position/PositionArea/Dock/BreakpointDisplay/Responsive), View (VBoundary, VLabel, VText, VForm, VActionForm, VInput/*, VSelect, VDropdown, VSwitch, VTextArea, VImage, VSvg, VBackground, VAnimation, VTooltip, VLoading, VErrorBoundary, VEllipse/VLine/VRectangle, VHyperlink, VMask, VFrame, VTheme, VBadge, VTemplate, VMount, VHeader/VNav/VMain/VAside/VFooter, VHR, VSection, VZone, VAudio, VVideo, VShadow), Enums, Types, utilities
|
|
24
|
+
- **web** (`@fewbox/den-web`): core + Debug, VGoogleFont, VChromeExtensionValidator, GoogleGrant, GoogleSignin, FigmaSignin, WeComSignin, parseJWT
|
|
25
|
+
- **app** (`@fewbox/den-app`): web + VDynamic, VAvatar, VBlock, VCard, VCardMedia, VCardSocial, VCardWindow, VPhoto, VStack, VTree
|
|
26
|
+
- **app** also exports: FewBox (boot, BootClass), Language, Network, Store modules
|
|
27
|
+
- **append** (`@fewbox/den-append`, no UI components): FewBox, Language, Network, Store modules only
|
|
33
28
|
|
|
34
29
|
## Core Concepts
|
|
35
30
|
|
|
@@ -41,35 +36,35 @@ All components extend `IBaseProps` (which extends `IViewProps`) providing these
|
|
|
41
36
|
|------|------|-------------|
|
|
42
37
|
| `className` | `string` | Additional CSS classes |
|
|
43
38
|
| `style` | `CSSProperties` | Inline styles |
|
|
44
|
-
| `fontSize` | `FontSizeType \|
|
|
39
|
+
| `fontSize` | `FontSizeType \| Property.FontSize` | Font size preset or custom CSS value |
|
|
45
40
|
| `isAutoSize` | `boolean` | Use auto-responsive font size variant |
|
|
46
41
|
| `fontWeight` | `FontWeightType` | Font weight (Thin through Black) |
|
|
47
|
-
| `frontColor` | `ColorType \|
|
|
48
|
-
| `backgroundColor` | `ColorType \|
|
|
49
|
-
| `borderColor` | `ColorType \|
|
|
42
|
+
| `frontColor` | `ColorType \| Property.Color` | Text/foreground color |
|
|
43
|
+
| `backgroundColor` | `ColorType \| Property.Color` | Background color |
|
|
44
|
+
| `borderColor` | `ColorType \| Property.Color` | Border color |
|
|
50
45
|
| `borderDirection` | `DirectionType` | Which sides get the border |
|
|
51
|
-
| `borderRadius` | `BorderRadiusType \|
|
|
52
|
-
| `borderStyle` | `BorderStyleType \|
|
|
53
|
-
| `borderWidth` | `BorderWidthType \|
|
|
54
|
-
| `padding` | `PaddingType \|
|
|
55
|
-
| `margin` | `MarginType \|
|
|
56
|
-
| `opacity` | `OpacityType` | Opacity preset |
|
|
57
|
-
| `display` | `DisplayType \|
|
|
58
|
-
| `visibility` | `VisibilityType \|
|
|
59
|
-
| `cursor` | `CursorType \|
|
|
60
|
-
| `overflow` | `OverflowType \|
|
|
61
|
-
| `overflowX` | `OverflowXType \|
|
|
62
|
-
| `overflowY` | `OverflowYType \|
|
|
63
|
-
| `width` | `
|
|
64
|
-
| `height` | `
|
|
65
|
-
| `minWidth` | `
|
|
66
|
-
| `minHeight` | `
|
|
67
|
-
| `maxWidth` | `
|
|
68
|
-
| `maxHeight` | `
|
|
69
|
-
| `zIndex` | `
|
|
70
|
-
| `fontFamily` | `
|
|
71
|
-
| `letterSpacing` | `
|
|
72
|
-
| `lineHeight` | `
|
|
46
|
+
| `borderRadius` | `BorderRadiusType \| Property.BorderRadius` | Border radius preset or custom |
|
|
47
|
+
| `borderStyle` | `BorderStyleType \| Property.BorderStyle` | Border style preset or custom |
|
|
48
|
+
| `borderWidth` | `BorderWidthType \| Property.BorderWidth` | Border width preset or custom |
|
|
49
|
+
| `padding` | `PaddingType \| Property.Padding` | CSS padding (preset or custom) |
|
|
50
|
+
| `margin` | `MarginType \| Property.Margin` | CSS margin (preset or custom) |
|
|
51
|
+
| `opacity` | `OpacityType \| Property.Opacity` | Opacity preset or custom CSS value |
|
|
52
|
+
| `display` | `DisplayType \| Property.Display` | CSS display preset or custom |
|
|
53
|
+
| `visibility` | `VisibilityType \| Property.Visibility` | CSS visibility preset or custom |
|
|
54
|
+
| `cursor` | `CursorType \| Property.Cursor` | CSS cursor preset or custom |
|
|
55
|
+
| `overflow` | `OverflowType \| Property.Overflow` | CSS overflow preset or custom |
|
|
56
|
+
| `overflowX` | `OverflowXType \| Property.OverflowX` | CSS overflow-x preset or custom |
|
|
57
|
+
| `overflowY` | `OverflowYType \| Property.OverflowY` | CSS overflow-y preset or custom |
|
|
58
|
+
| `width` | `Property.Width` | CSS width |
|
|
59
|
+
| `height` | `Property.Height` | CSS height |
|
|
60
|
+
| `minWidth` | `Property.Width` | CSS min-width |
|
|
61
|
+
| `minHeight` | `Property.Width` | CSS min-height |
|
|
62
|
+
| `maxWidth` | `Property.Width` | CSS max-width |
|
|
63
|
+
| `maxHeight` | `Property.Width` | CSS max-height |
|
|
64
|
+
| `zIndex` | `Property.ZIndex` | CSS z-index |
|
|
65
|
+
| `fontFamily` | `Property.FontFamily` | CSS font-family |
|
|
66
|
+
| `letterSpacing` | `LetterSpacingType \| Property.LetterSpacing` | Letter spacing preset or custom CSS value |
|
|
67
|
+
| `lineHeight` | `Property.LineHeight` | CSS line-height |
|
|
73
68
|
| `selfShrink` | `number` | flex-shrink for the component itself |
|
|
74
69
|
| `selfGrow` | `number` | flex-grow for the component itself |
|
|
75
70
|
| `selfBasis` | `string` | flex-basis for the component itself |
|
|
@@ -146,7 +141,7 @@ FontWeightType.Black // 900
|
|
|
146
141
|
|
|
147
142
|
### Preset Enums (class-based styling)
|
|
148
143
|
|
|
149
|
-
These enums generate CSS classes.
|
|
144
|
+
These enums generate CSS classes. All `Full*Type` props accept either a preset enum value (applied as className) or a custom CSS value from `csstype` `Property.*` (applied as inline style):
|
|
150
145
|
|
|
151
146
|
```tsx
|
|
152
147
|
// Border Radius
|
|
@@ -167,6 +162,9 @@ MarginType.Default | .Normal | .ExtraSmall | .Small | .Large | .ExtraLarge
|
|
|
167
162
|
// Gap (for layout components)
|
|
168
163
|
GapType.Default | .Normal | .ExtraSmall | .Small | .Large | .ExtraLarge
|
|
169
164
|
|
|
165
|
+
// Letter Spacing
|
|
166
|
+
LetterSpacingType.Default | .Normal | .ExtraSmall | .Small | .Large | .ExtraLarge
|
|
167
|
+
|
|
170
168
|
// Opacity
|
|
171
169
|
OpacityType._0 | ._10 | ._20 | ._25 | ._30 | ._40 | ._50 | ._60 | ._70 | ._75 | ._80 | ._90 | ._100
|
|
172
170
|
|
|
@@ -193,53 +191,53 @@ All X-series components accept `gap`, `cross`, `itemsShrink` props in addition t
|
|
|
193
191
|
|
|
194
192
|
```tsx
|
|
195
193
|
// Basic horizontal layout (default: justify-content: flex-start)
|
|
196
|
-
<
|
|
194
|
+
<X gap="1em">
|
|
197
195
|
<Child1 /> <Child2 /> <Child3 />
|
|
198
|
-
</
|
|
196
|
+
</X>
|
|
199
197
|
|
|
200
198
|
// Justify-content variants:
|
|
201
|
-
<
|
|
202
|
-
<
|
|
203
|
-
<
|
|
204
|
-
<
|
|
205
|
-
<
|
|
206
|
-
<
|
|
199
|
+
<XLeft>...</XLeft> // flex-start
|
|
200
|
+
<XCenter>...</XCenter> // center
|
|
201
|
+
<XRight>...</XRight> // flex-end
|
|
202
|
+
<XBetween>...</XBetween> // space-between
|
|
203
|
+
<XAround>...</XAround> // space-around
|
|
204
|
+
<XEvenly>...</XEvenly> // space-evenly
|
|
207
205
|
|
|
208
206
|
// Auto-margin variants (margin-based centering):
|
|
209
|
-
<
|
|
210
|
-
<
|
|
211
|
-
<
|
|
212
|
-
<
|
|
213
|
-
<
|
|
214
|
-
<
|
|
207
|
+
<XAutoLeft>...</XAutoLeft> // first child margin-right: auto
|
|
208
|
+
<XAutoCenter>...</XAutoCenter> // center child with auto margins
|
|
209
|
+
<XAutoRight>...</XAutoRight> // last child margin-left: auto
|
|
210
|
+
<XAutoLefts>...</XAutoLefts> // all items margin-right: auto
|
|
211
|
+
<XAutoRights>...</XAutoRights> // all items margin-left: auto
|
|
212
|
+
<XAutoBoth>...</XAutoBoth> // first and last with auto margins
|
|
215
213
|
|
|
216
214
|
// Custom flex-basis distribution:
|
|
217
|
-
<
|
|
215
|
+
<XCustom basises={['20%', '30%', '50%']}>
|
|
218
216
|
<Child1 /> <Child2 /> <Child3 />
|
|
219
|
-
</
|
|
217
|
+
</XCustom>
|
|
220
218
|
|
|
221
219
|
// Uniform flex-basis with auto-margin sides:
|
|
222
|
-
<
|
|
220
|
+
<XCustomBoth basis="10%">
|
|
223
221
|
<Child1 /> <Child2 /> <Child3 />
|
|
224
|
-
</
|
|
222
|
+
</XCustomBoth>
|
|
225
223
|
|
|
226
224
|
// Wrap variants (flex-wrap: wrap with align-content):
|
|
227
|
-
<
|
|
228
|
-
<
|
|
229
|
-
<
|
|
230
|
-
<
|
|
231
|
-
<
|
|
232
|
-
<
|
|
225
|
+
<XWrapTop>...</XWrapTop> // align-content: flex-start
|
|
226
|
+
<XWrapMiddle>...</XWrapMiddle> // align-content: center
|
|
227
|
+
<XWrapBottom>...</XWrapBottom> // align-content: flex-end
|
|
228
|
+
<XWrapAround>...</XWrapAround> // align-content: space-around
|
|
229
|
+
<XWrapBetween>...</XWrapBetween> // align-content: space-between
|
|
230
|
+
<XWrapEvenly>...</XWrapEvenly> // align-content: space-evenly
|
|
233
231
|
```
|
|
234
232
|
|
|
235
233
|
**Cross-axis alignment** (align-items) via the `cross` prop on X components:
|
|
236
234
|
|
|
237
235
|
```tsx
|
|
238
|
-
<
|
|
239
|
-
<
|
|
240
|
-
<
|
|
241
|
-
<
|
|
242
|
-
<
|
|
236
|
+
<X cross={XCrossType.Top}> // align-items: flex-start
|
|
237
|
+
<X cross={XCrossType.Middle}> // align-items: center
|
|
238
|
+
<X cross={XCrossType.Bottom}> // align-items: flex-end
|
|
239
|
+
<X cross={XCrossType.Stretch}> // align-items: stretch
|
|
240
|
+
<X cross={XCrossType.Baseline}> // align-items: baseline
|
|
243
241
|
```
|
|
244
242
|
|
|
245
243
|
### Y-Series (Vertical Layout, flex-direction: column)
|
|
@@ -247,43 +245,43 @@ All X-series components accept `gap`, `cross`, `itemsShrink` props in addition t
|
|
|
247
245
|
Mirrors X-series but vertically:
|
|
248
246
|
|
|
249
247
|
```tsx
|
|
250
|
-
<
|
|
251
|
-
<
|
|
252
|
-
<
|
|
253
|
-
<
|
|
254
|
-
<
|
|
255
|
-
<
|
|
256
|
-
<
|
|
248
|
+
<Y gap="1em">...</Y> // default
|
|
249
|
+
<YTop>...</YTop> // justify-content: flex-start
|
|
250
|
+
<YMiddle>...</YMiddle> // justify-content: center
|
|
251
|
+
<YBottom>...</YBottom> // justify-content: flex-end
|
|
252
|
+
<YBetween>...</YBetween> // space-between
|
|
253
|
+
<YAround>...</YAround> // space-around
|
|
254
|
+
<YEvenly>...</YEvenly> // space-evenly
|
|
257
255
|
|
|
258
256
|
// Auto-margin variants:
|
|
259
|
-
<
|
|
260
|
-
<
|
|
261
|
-
<
|
|
262
|
-
<
|
|
263
|
-
<
|
|
264
|
-
<
|
|
257
|
+
<YAutoTop>...</YAutoTop>
|
|
258
|
+
<YAutoCenter>...</YAutoCenter>
|
|
259
|
+
<YAutoBottom>...</YAutoBottom>
|
|
260
|
+
<YAutoTops>...</YAutoTops>
|
|
261
|
+
<YAutoBottoms>...</YAutoBottoms>
|
|
262
|
+
<YAutoBoth>...</YAutoBoth>
|
|
265
263
|
|
|
266
264
|
// Custom:
|
|
267
|
-
<
|
|
268
|
-
<
|
|
265
|
+
<YCustom basises={['auto', '1fr', 'auto']}>...</YCustom>
|
|
266
|
+
<YCustomBoth basis="10%">...</YCustomBoth>
|
|
269
267
|
|
|
270
268
|
// Wrap variants:
|
|
271
|
-
<
|
|
272
|
-
<
|
|
273
|
-
<
|
|
274
|
-
<
|
|
275
|
-
<
|
|
276
|
-
<
|
|
269
|
+
<YWrapLeft>...</YWrapLeft>
|
|
270
|
+
<YWrapCenter>...</YWrapCenter>
|
|
271
|
+
<YWrapRight>...</YWrapRight>
|
|
272
|
+
<YWrapAround>...</YWrapAround>
|
|
273
|
+
<YWrapBetween>...</YWrapBetween>
|
|
274
|
+
<YWrapEvenly>...</YWrapEvenly>
|
|
277
275
|
```
|
|
278
276
|
|
|
279
277
|
**Cross-axis alignment** (align-items) via the `cross` prop on Y components:
|
|
280
278
|
|
|
281
279
|
```tsx
|
|
282
|
-
<
|
|
283
|
-
<
|
|
284
|
-
<
|
|
285
|
-
<
|
|
286
|
-
<
|
|
280
|
+
<Y cross={YCrossType.Left}> // align-items: flex-start
|
|
281
|
+
<Y cross={YCrossType.Center}> // align-items: center
|
|
282
|
+
<Y cross={YCrossType.Right}> // align-items: flex-end
|
|
283
|
+
<Y cross={YCrossType.Stretch}> // align-items: stretch
|
|
284
|
+
<Y cross={YCrossType.Baseline}> // align-items: baseline
|
|
287
285
|
```
|
|
288
286
|
|
|
289
287
|
### S-Series (Individual Item Cross-axis Override)
|
|
@@ -291,36 +289,36 @@ Mirrors X-series but vertically:
|
|
|
291
289
|
Wrap a child in an S-component to override the parent's cross-axis alignment for that child only:
|
|
292
290
|
|
|
293
291
|
```tsx
|
|
294
|
-
<
|
|
292
|
+
<XCenter cross={XCrossType.Bottom} height="6em">
|
|
295
293
|
<Child1 /> {/* aligned to bottom */}
|
|
296
294
|
<Child2 /> {/* aligned to bottom */}
|
|
297
|
-
<
|
|
295
|
+
<STop>
|
|
298
296
|
<Child3 /> {/* overridden to top */}
|
|
299
|
-
</
|
|
300
|
-
</
|
|
297
|
+
</STop>
|
|
298
|
+
</XCenter>
|
|
301
299
|
|
|
302
300
|
// Available S-components:
|
|
303
|
-
<
|
|
304
|
-
<
|
|
305
|
-
<
|
|
306
|
-
<
|
|
307
|
-
<
|
|
308
|
-
<
|
|
309
|
-
<
|
|
310
|
-
<
|
|
301
|
+
<STop>...</STop> // align-self: flex-start
|
|
302
|
+
<SMiddle>...</SMiddle> // align-self: center
|
|
303
|
+
<SBottom>...</SBottom> // align-self: flex-end
|
|
304
|
+
<SLeft>...</SLeft> // align-self: flex-start (in Y container)
|
|
305
|
+
<SCenter>...</SCenter> // align-self: center (in Y container)
|
|
306
|
+
<SRight>...</SRight> // align-self: flex-end (in Y container)
|
|
307
|
+
<SStretch>...</SStretch> // align-self: stretch
|
|
308
|
+
<SBaseline>...</SBaseline>// align-self: baseline
|
|
311
309
|
```
|
|
312
310
|
|
|
313
311
|
### Position & PositionArea
|
|
314
312
|
|
|
315
313
|
```tsx
|
|
316
314
|
// PositionArea establishes a positioning context (position: relative) on its child.
|
|
317
|
-
<
|
|
318
|
-
<
|
|
319
|
-
<
|
|
315
|
+
<PositionArea category={PositionAreaCategory.FullSize}>
|
|
316
|
+
<VBoundary height="250px" backgroundColor={ColorType.Dark}>
|
|
317
|
+
<Position category={PositionCategory.Area} type={PositionType.Center}>
|
|
320
318
|
<Content />
|
|
321
|
-
</
|
|
322
|
-
</
|
|
323
|
-
</
|
|
319
|
+
</Position>
|
|
320
|
+
</VBoundary>
|
|
321
|
+
</PositionArea>
|
|
324
322
|
|
|
325
323
|
// PositionAreaCategory:
|
|
326
324
|
// Default = inline-block container
|
|
@@ -336,14 +334,14 @@ Wrap a child in an S-component to override the parent's cross-axis alignment for
|
|
|
336
334
|
// Top, Right, Bottom, Left, LeftTop, RightTop, LeftBottom, RightBottom, Center
|
|
337
335
|
|
|
338
336
|
// Custom positioning (omit type, set top/right/bottom/left):
|
|
339
|
-
<
|
|
337
|
+
<Position category={PositionCategory.Area} top="20px" left="30px">
|
|
340
338
|
<Content />
|
|
341
|
-
</
|
|
339
|
+
</Position>
|
|
342
340
|
|
|
343
341
|
// Sticky navbar example:
|
|
344
|
-
<
|
|
342
|
+
<Position category={PositionCategory.Edge} top="0px" isFullWidth zIndex={10}>
|
|
345
343
|
<NavBar />
|
|
346
|
-
</
|
|
344
|
+
</Position>
|
|
347
345
|
|
|
348
346
|
// Position props: category (required), type, top, right, bottom, left, zIndex, isFullWidth
|
|
349
347
|
```
|
|
@@ -353,13 +351,13 @@ Wrap a child in an S-component to override the parent's cross-axis alignment for
|
|
|
353
351
|
```tsx
|
|
354
352
|
// Dock positions an overlay relative to its children.
|
|
355
353
|
// renderOverlay is REQUIRED — returns the overlay element.
|
|
356
|
-
<
|
|
357
|
-
category={
|
|
354
|
+
<Dock
|
|
355
|
+
category={DockCategory.Top}
|
|
358
356
|
offset={4}
|
|
359
357
|
renderOverlay={() => <div>Tooltip above</div>}
|
|
360
358
|
>
|
|
361
359
|
<button>Hover me</button>
|
|
362
|
-
</
|
|
360
|
+
</Dock>
|
|
363
361
|
|
|
364
362
|
// DockCategory:
|
|
365
363
|
// Top, Right, Bottom, Left
|
|
@@ -370,15 +368,33 @@ Wrap a child in an S-component to override the parent's cross-axis alignment for
|
|
|
370
368
|
// DockAlignment (only for corner categories like LeftTop, RightTop, etc.):
|
|
371
369
|
// Horizontal, Vertical
|
|
372
370
|
|
|
371
|
+
// DockPopoverMode (controls overlay visibility behavior):
|
|
372
|
+
// Manual — overlay visibility controlled by isOverlayVisible prop
|
|
373
|
+
// Auto — overlay uses CSS Anchor Positioning with browser popover API
|
|
374
|
+
|
|
373
375
|
// Corner with alignment:
|
|
374
|
-
<
|
|
375
|
-
category={
|
|
376
|
-
alignment={
|
|
376
|
+
<Dock
|
|
377
|
+
category={DockCategory.LeftTop}
|
|
378
|
+
alignment={DockAlignment.Horizontal}
|
|
377
379
|
offset={4}
|
|
378
380
|
renderOverlay={() => <DropdownMenu />}
|
|
379
381
|
>
|
|
380
382
|
<TriggerButton />
|
|
381
|
-
</
|
|
383
|
+
</Dock>
|
|
384
|
+
|
|
385
|
+
// With popover mode and visibility control:
|
|
386
|
+
<Dock
|
|
387
|
+
category={DockCategory.Bottom}
|
|
388
|
+
offset={4}
|
|
389
|
+
isOverlayVisible={isOpen}
|
|
390
|
+
popoverMode={DockPopoverMode.Manual}
|
|
391
|
+
overlayZIndex={9999}
|
|
392
|
+
isPortal={false}
|
|
393
|
+
onOverlayClose={() => setIsOpen(false)}
|
|
394
|
+
renderOverlay={() => <DropdownContent />}
|
|
395
|
+
>
|
|
396
|
+
<button onClick={() => setIsOpen(!isOpen)}>Toggle</button>
|
|
397
|
+
</Dock>
|
|
382
398
|
```
|
|
383
399
|
|
|
384
400
|
### BreakpointDisplay (Responsive Show/Hide)
|
|
@@ -391,40 +407,40 @@ Wrap a child in an S-component to override the parent's cross-axis alignment for
|
|
|
391
407
|
// ScreenSizeType: ExtraSmall, Small, Medium, Large, ExtraLarge, ExtraExtraLarge
|
|
392
408
|
|
|
393
409
|
// Always visible
|
|
394
|
-
<
|
|
410
|
+
<BreakpointDisplay category={BreakpointCategory.Visible}>
|
|
395
411
|
<div>Always shown</div>
|
|
396
|
-
</
|
|
412
|
+
</BreakpointDisplay>
|
|
397
413
|
|
|
398
414
|
// Always hidden
|
|
399
|
-
<
|
|
415
|
+
<BreakpointDisplay category={BreakpointCategory.Hidden}>
|
|
400
416
|
<div>Always hidden</div>
|
|
401
|
-
</
|
|
417
|
+
</BreakpointDisplay>
|
|
402
418
|
|
|
403
419
|
// Responsive: visible only on Medium breakpoint
|
|
404
|
-
<
|
|
405
|
-
category={
|
|
406
|
-
type={
|
|
407
|
-
breakpoint={
|
|
420
|
+
<BreakpointDisplay
|
|
421
|
+
category={BreakpointCategory.Visible}
|
|
422
|
+
type={BreakpointType.Only}
|
|
423
|
+
breakpoint={ScreenSizeType.Medium}
|
|
408
424
|
>
|
|
409
425
|
<div>Medium only</div>
|
|
410
|
-
</
|
|
426
|
+
</BreakpointDisplay>
|
|
411
427
|
|
|
412
428
|
// Hidden on Small and below
|
|
413
|
-
<
|
|
414
|
-
category={
|
|
415
|
-
type={
|
|
416
|
-
breakpoint={
|
|
429
|
+
<BreakpointDisplay
|
|
430
|
+
category={BreakpointCategory.Hidden}
|
|
431
|
+
type={BreakpointType.Down}
|
|
432
|
+
breakpoint={ScreenSizeType.Small}
|
|
417
433
|
>
|
|
418
434
|
<div>Hidden on mobile</div>
|
|
419
|
-
</
|
|
435
|
+
</BreakpointDisplay>
|
|
420
436
|
|
|
421
437
|
// Multiple breakpoints (array):
|
|
422
|
-
<
|
|
423
|
-
category={
|
|
424
|
-
breakpoint={[
|
|
438
|
+
<BreakpointDisplay
|
|
439
|
+
category={BreakpointCategory.Visible}
|
|
440
|
+
breakpoint={[ScreenSizeType.Small, ScreenSizeType.Large]}
|
|
425
441
|
>
|
|
426
442
|
<div>Visible on Small and Large</div>
|
|
427
|
-
</
|
|
443
|
+
</BreakpointDisplay>
|
|
428
444
|
```
|
|
429
445
|
|
|
430
446
|
### Responsive (Desktop/Mobile Switch)
|
|
@@ -432,8 +448,8 @@ Wrap a child in an S-component to override the parent's cross-axis alignment for
|
|
|
432
448
|
```tsx
|
|
433
449
|
// Shorthand for showing desktop or mobile content based on breakpoint.
|
|
434
450
|
// Children must accept className prop (uses BreakpointDisplay internally).
|
|
435
|
-
<
|
|
436
|
-
breakpointType={
|
|
451
|
+
<Responsive
|
|
452
|
+
breakpointType={ScreenSizeType.Medium}
|
|
437
453
|
desktop={<div>Desktop layout</div>}
|
|
438
454
|
mobile={<div>Mobile layout</div>}
|
|
439
455
|
/>
|
|
@@ -445,9 +461,9 @@ Wrap a child in an S-component to override the parent's cross-axis alignment for
|
|
|
445
461
|
// Like Bootstrap's Container — constrains max-width and centers content.
|
|
446
462
|
// Category controls at which breakpoint max-width starts applying.
|
|
447
463
|
// Below the breakpoint: full width. Above: max-width grows per tier.
|
|
448
|
-
<
|
|
464
|
+
<VZone category={ZoneCategory.Small} padding="1em">
|
|
449
465
|
<Content />
|
|
450
|
-
</
|
|
466
|
+
</VZone>
|
|
451
467
|
|
|
452
468
|
// ZoneCategory:
|
|
453
469
|
// Fluid — always 100%, no max-width
|
|
@@ -462,20 +478,20 @@ Wrap a child in an S-component to override the parent's cross-axis alignment for
|
|
|
462
478
|
|
|
463
479
|
```tsx
|
|
464
480
|
// Flex — full flexbox control
|
|
465
|
-
<
|
|
466
|
-
direction={
|
|
467
|
-
wrap={
|
|
468
|
-
justifyContent={
|
|
469
|
-
alignItems={
|
|
481
|
+
<Flex
|
|
482
|
+
direction={FlexDirectionType.Row}
|
|
483
|
+
wrap={FlexWrapType.Wrap}
|
|
484
|
+
justifyContent={FlexJustifyContentType.SpaceBetween}
|
|
485
|
+
alignItems={FlexAlignItemsType.Center}
|
|
470
486
|
gap="1em"
|
|
471
487
|
>
|
|
472
488
|
...
|
|
473
|
-
</
|
|
489
|
+
</Flex>
|
|
474
490
|
|
|
475
491
|
// FlexItem — wraps a child with flex item properties
|
|
476
|
-
<
|
|
492
|
+
<FlexItem grow={1} shrink={0} basis="200px" order={2}>
|
|
477
493
|
<Content />
|
|
478
|
-
</
|
|
494
|
+
</FlexItem>
|
|
479
495
|
|
|
480
496
|
// FlexItem also exports FlexItemAlignSelfType
|
|
481
497
|
// Flex also exports FlexAlignContentType
|
|
@@ -490,14 +506,14 @@ Wrap a child in an S-component to override the parent's cross-axis alignment for
|
|
|
490
506
|
The basic div wrapper. Use as a general-purpose container:
|
|
491
507
|
|
|
492
508
|
```tsx
|
|
493
|
-
<
|
|
509
|
+
<VBoundary
|
|
494
510
|
padding="1em"
|
|
495
|
-
backgroundColor={
|
|
496
|
-
borderRadius={
|
|
511
|
+
backgroundColor={ColorType.Light}
|
|
512
|
+
borderRadius={BorderRadiusType.Default}
|
|
497
513
|
width="100%"
|
|
498
514
|
>
|
|
499
515
|
<Content />
|
|
500
|
-
</
|
|
516
|
+
</VBoundary>
|
|
501
517
|
```
|
|
502
518
|
|
|
503
519
|
### VLabel (Text/Label)
|
|
@@ -506,49 +522,61 @@ For inline text. Renders as `<span>` by default, configurable to any inline/head
|
|
|
506
522
|
|
|
507
523
|
```tsx
|
|
508
524
|
// Basic label
|
|
509
|
-
<
|
|
525
|
+
<VLabel caption="Hello World" />
|
|
510
526
|
|
|
511
527
|
// With heading category
|
|
512
|
-
<
|
|
513
|
-
category={
|
|
528
|
+
<VLabel
|
|
529
|
+
category={LabelCategory.H1}
|
|
514
530
|
caption="Page Title"
|
|
515
531
|
/>
|
|
516
532
|
|
|
517
533
|
// Styled label
|
|
518
|
-
<
|
|
519
|
-
fontSize={
|
|
520
|
-
fontWeight={
|
|
521
|
-
frontColor={
|
|
534
|
+
<VLabel
|
|
535
|
+
fontSize={FontSizeType.Large}
|
|
536
|
+
fontWeight={FontWeightType.Bold}
|
|
537
|
+
frontColor={ColorType.Primary}
|
|
522
538
|
caption="Important Text"
|
|
523
539
|
/>
|
|
524
540
|
|
|
525
541
|
// Circle label (badge)
|
|
526
|
-
<
|
|
527
|
-
type={
|
|
528
|
-
frontColor={
|
|
529
|
-
backgroundColor={
|
|
542
|
+
<VLabel
|
|
543
|
+
type={LabelType.Circle}
|
|
544
|
+
frontColor={ColorType.White}
|
|
545
|
+
backgroundColor={ColorType.Black}
|
|
530
546
|
caption="X"
|
|
531
547
|
/>
|
|
532
548
|
|
|
533
549
|
// Text overflow (ellipsis)
|
|
534
|
-
<
|
|
550
|
+
<VLabel
|
|
535
551
|
isTextOverflow
|
|
536
552
|
width="12em"
|
|
537
553
|
caption="This very long text will be truncated with ellipsis..."
|
|
538
554
|
/>
|
|
539
555
|
|
|
540
556
|
// Alignment
|
|
541
|
-
<
|
|
542
|
-
alignType={
|
|
557
|
+
<VLabel
|
|
558
|
+
alignType={LabelAlignType.Center}
|
|
543
559
|
caption="Centered text"
|
|
544
560
|
/>
|
|
545
561
|
|
|
546
562
|
// i18n with React Intl
|
|
547
|
-
<
|
|
563
|
+
<VLabel caption={<FormattedMessage id="Label.Hello" />} />
|
|
548
564
|
|
|
549
565
|
// Available categories:
|
|
550
566
|
// LabelCategory.Div, Span, H1-H6, Abbr, Strong, Em, Code, Pre,
|
|
551
567
|
// Blockquote, Mark, Del, Ins, Small, Sub, Sup, etc.
|
|
568
|
+
|
|
569
|
+
// fontWeight/fontSize with heading categories (H1-H6):
|
|
570
|
+
// When fontWeight or fontSize is set, VLabel adds CSS classes
|
|
571
|
+
// (.v-label-inherit-font-weight / .v-label-inherit-font-size)
|
|
572
|
+
// that apply `inherit` to the inner heading element, overriding
|
|
573
|
+
// browser defaults. Without these props, headings keep their
|
|
574
|
+
// browser default styles (e.g., H1 is bold and 2em).
|
|
575
|
+
<VLabel
|
|
576
|
+
category={LabelCategory.H1}
|
|
577
|
+
fontWeight={FontWeightType.Thin}
|
|
578
|
+
caption="Thin H1"
|
|
579
|
+
/>
|
|
552
580
|
```
|
|
553
581
|
|
|
554
582
|
### VText (Block Text)
|
|
@@ -556,13 +584,13 @@ For inline text. Renders as `<span>` by default, configurable to any inline/head
|
|
|
556
584
|
For block-level text (p, article, section, etc.):
|
|
557
585
|
|
|
558
586
|
```tsx
|
|
559
|
-
<
|
|
560
|
-
category={
|
|
587
|
+
<VText
|
|
588
|
+
category={TextCategory.P}
|
|
561
589
|
caption="Paragraph text content."
|
|
562
590
|
/>
|
|
563
591
|
|
|
564
|
-
<
|
|
565
|
-
alignType={
|
|
592
|
+
<VText
|
|
593
|
+
alignType={TextAlignType.Center}
|
|
566
594
|
renderContent={() => <span>Complex <strong>content</strong></span>}
|
|
567
595
|
/>
|
|
568
596
|
```
|
|
@@ -571,20 +599,20 @@ For block-level text (p, article, section, etc.):
|
|
|
571
599
|
|
|
572
600
|
```tsx
|
|
573
601
|
// Renders an <a> tag. Requires category and to props.
|
|
574
|
-
<
|
|
575
|
-
category={
|
|
602
|
+
<VHyperlink
|
|
603
|
+
category={HyperlinkCategory.Self}
|
|
576
604
|
to="/about"
|
|
577
605
|
>
|
|
578
606
|
Click me
|
|
579
|
-
</
|
|
607
|
+
</VHyperlink>
|
|
580
608
|
|
|
581
609
|
// Open in new window
|
|
582
|
-
<
|
|
583
|
-
category={
|
|
610
|
+
<VHyperlink
|
|
611
|
+
category={HyperlinkCategory.NewWindow}
|
|
584
612
|
to="https://example.com"
|
|
585
613
|
>
|
|
586
614
|
External link
|
|
587
|
-
</
|
|
615
|
+
</VHyperlink>
|
|
588
616
|
|
|
589
617
|
// HyperlinkCategory: NewWindow (_blank), Self (_self), Parent (_parent), Top (_top)
|
|
590
618
|
```
|
|
@@ -594,7 +622,7 @@ For block-level text (p, article, section, etc.):
|
|
|
594
622
|
#### VForm (Form Container)
|
|
595
623
|
|
|
596
624
|
```tsx
|
|
597
|
-
<
|
|
625
|
+
<VForm
|
|
598
626
|
handleSubmit={(data) => {
|
|
599
627
|
// data is automatically converted from FormData to nested JSON
|
|
600
628
|
// e.g., { form: { username: "value", password: "value" } }
|
|
@@ -606,21 +634,21 @@ For block-level text (p, article, section, etc.):
|
|
|
606
634
|
invalidInputs[0]?.focus();
|
|
607
635
|
}}
|
|
608
636
|
>
|
|
609
|
-
<
|
|
610
|
-
<
|
|
611
|
-
<
|
|
612
|
-
<
|
|
613
|
-
</
|
|
614
|
-
</
|
|
637
|
+
<Y gap="0.5em">
|
|
638
|
+
<VTextBox name="form.username" placeholder="Username" />
|
|
639
|
+
<VPassword name="form.password" placeholder="Password" />
|
|
640
|
+
<VSubmit caption="Submit" />
|
|
641
|
+
</Y>
|
|
642
|
+
</VForm>
|
|
615
643
|
|
|
616
644
|
// HandleSubmitCategory: Json (default), FormData
|
|
617
645
|
// Use FormData category to receive raw FormData instead of parsed JSON:
|
|
618
|
-
<
|
|
619
|
-
handleSubmitCategory={
|
|
646
|
+
<VForm
|
|
647
|
+
handleSubmitCategory={HandleSubmitCategory.FormData}
|
|
620
648
|
handleSubmit={(formData) => { /* formData is FormData */ }}
|
|
621
649
|
>
|
|
622
650
|
...
|
|
623
|
-
</
|
|
651
|
+
</VForm>
|
|
624
652
|
```
|
|
625
653
|
|
|
626
654
|
#### VActionForm (Simple Form)
|
|
@@ -628,10 +656,10 @@ For block-level text (p, article, section, etc.):
|
|
|
628
656
|
A simple `<form>` wrapper without JSON conversion or validation handling:
|
|
629
657
|
|
|
630
658
|
```tsx
|
|
631
|
-
<
|
|
659
|
+
<VActionForm action="/api/submit" method="POST">
|
|
632
660
|
<input name="field" />
|
|
633
661
|
<button type="submit">Submit</button>
|
|
634
|
-
</
|
|
662
|
+
</VActionForm>
|
|
635
663
|
```
|
|
636
664
|
|
|
637
665
|
**Form data naming conventions:**
|
|
@@ -643,7 +671,7 @@ A simple `<form>` wrapper without JSON conversion or validation handling:
|
|
|
643
671
|
|
|
644
672
|
```tsx
|
|
645
673
|
// Text input
|
|
646
|
-
<
|
|
674
|
+
<VTextBox
|
|
647
675
|
name="form.name"
|
|
648
676
|
placeholder="Enter name"
|
|
649
677
|
label="Name" // Floating label
|
|
@@ -655,70 +683,70 @@ A simple `<form>` wrapper without JSON conversion or validation handling:
|
|
|
655
683
|
|
|
656
684
|
// Controlled input with hooks
|
|
657
685
|
const [value, setValue] = useState('');
|
|
658
|
-
<
|
|
686
|
+
<VTextBox
|
|
659
687
|
name="form.search"
|
|
660
688
|
valueHook={value}
|
|
661
689
|
setStateHook={setValue}
|
|
662
690
|
/>
|
|
663
691
|
|
|
664
692
|
// With suffix options
|
|
665
|
-
<
|
|
693
|
+
<VTextBox
|
|
666
694
|
renderOptions={(inputRef) => (
|
|
667
|
-
<
|
|
695
|
+
<VSvg onClick={() => alert(inputRef.current?.value)}>
|
|
668
696
|
<SearchIcon />
|
|
669
|
-
</
|
|
697
|
+
</VSvg>
|
|
670
698
|
)}
|
|
671
699
|
/>
|
|
672
700
|
|
|
673
701
|
// Other input types:
|
|
674
|
-
<
|
|
675
|
-
<
|
|
676
|
-
<
|
|
677
|
-
<
|
|
678
|
-
<
|
|
679
|
-
<
|
|
680
|
-
<
|
|
681
|
-
<
|
|
682
|
-
<
|
|
683
|
-
<
|
|
684
|
-
<
|
|
685
|
-
<
|
|
686
|
-
<
|
|
702
|
+
<VEmail name="form.email" required placeholder="Email" />
|
|
703
|
+
<VPassword name="form.password" placeholder="Password" />
|
|
704
|
+
<VNumber name="form.count" min={0} max={100} />
|
|
705
|
+
<VDate name="form.date" />
|
|
706
|
+
<VDatetimeLocal name="form.datetime" />
|
|
707
|
+
<VTime name="form.time" />
|
|
708
|
+
<VMonth name="form.month" />
|
|
709
|
+
<VWeek name="form.week" />
|
|
710
|
+
<VColor name="form.color" />
|
|
711
|
+
<VTel name="form.phone" />
|
|
712
|
+
<VUrl name="form.website" />
|
|
713
|
+
<VSearch name="form.search" />
|
|
714
|
+
<VRange name="form.volume" min={0} max={100} />
|
|
687
715
|
|
|
688
716
|
// TextArea
|
|
689
|
-
<
|
|
717
|
+
<VTextArea name="form.bio" rows={6} placeholder="Bio" />
|
|
690
718
|
|
|
691
719
|
// Checkbox
|
|
692
|
-
<
|
|
720
|
+
<VCheckBox
|
|
693
721
|
id="form.agree"
|
|
694
722
|
name="form.agree"
|
|
695
723
|
label="I agree"
|
|
696
724
|
isChecked={true}
|
|
697
|
-
frontColor={
|
|
725
|
+
frontColor={ColorType.Primary}
|
|
698
726
|
/>
|
|
699
727
|
|
|
700
728
|
// Radio
|
|
701
|
-
<
|
|
702
|
-
<
|
|
729
|
+
<VRadio id="opt1" name="form.option" value="A" label="Option A" />
|
|
730
|
+
<VRadio id="opt2" name="form.option" value="B" label="Option B" />
|
|
703
731
|
|
|
704
732
|
// Radio Group (managed state)
|
|
705
|
-
<
|
|
733
|
+
<VGroup
|
|
706
734
|
selectedValue="A"
|
|
707
735
|
renderGroup={(selectedValue, handleSelect) => (
|
|
708
736
|
<>
|
|
709
|
-
<
|
|
737
|
+
<VRadio id="opt1" name="form.option" value="A" label="A"
|
|
710
738
|
isChecked={selectedValue === 'A'} onChange={handleSelect} />
|
|
711
|
-
<
|
|
739
|
+
<VRadio id="opt2" name="form.option" value="B" label="B"
|
|
712
740
|
isChecked={selectedValue === 'B'} onChange={handleSelect} />
|
|
713
741
|
</>
|
|
714
742
|
)}
|
|
715
743
|
/>
|
|
716
744
|
|
|
717
745
|
// Hidden field
|
|
718
|
-
<
|
|
746
|
+
<VHidden name="form.id" value="123" />
|
|
719
747
|
|
|
720
748
|
// Select (native <select>)
|
|
721
|
-
<
|
|
749
|
+
<VSelect
|
|
722
750
|
name="form.country"
|
|
723
751
|
items={[
|
|
724
752
|
{ caption: 'USA', value: 'us' },
|
|
@@ -729,7 +757,7 @@ const [value, setValue] = useState('');
|
|
|
729
757
|
// ISelectItemData: { caption: string; value: string }
|
|
730
758
|
|
|
731
759
|
// Dropdown (custom dropdown with icons)
|
|
732
|
-
<
|
|
760
|
+
<VDropdown
|
|
733
761
|
name="form.category"
|
|
734
762
|
items={[
|
|
735
763
|
{ caption: 'Option A', value: 'a', icon: <IconA /> },
|
|
@@ -739,19 +767,26 @@ const [value, setValue] = useState('');
|
|
|
739
767
|
downIcon={<DownArrowIcon />} // required
|
|
740
768
|
upIcon={<UpArrowIcon />} // required
|
|
741
769
|
enableClear
|
|
770
|
+
readOnly // renders as VLabel (non-interactive)
|
|
771
|
+
isSelectOnly // prevents manual typing, only allows selection from items
|
|
772
|
+
menuGap="4px" // gap between dropdown menu and trigger
|
|
773
|
+
menuBackgroundColor={ColorType.White}
|
|
774
|
+
menuZIndex={9999}
|
|
742
775
|
handleChange={(value) => console.log(value)}
|
|
776
|
+
overWriteDropdownMenu={(items) => <CustomMenu items={items} />} // custom menu renderer
|
|
777
|
+
overWriteDropdownItem={(item) => <CustomItem item={item} />} // custom item renderer
|
|
743
778
|
/>
|
|
744
779
|
// IDropdownItemData: { caption: string; value: string; icon?: JSX.Element }
|
|
745
780
|
|
|
746
781
|
// Switch
|
|
747
|
-
<
|
|
782
|
+
<VSwitch
|
|
748
783
|
isOn={true}
|
|
749
784
|
icon={<SwitchIcon />}
|
|
750
785
|
onSwitch={(isOn) => console.log(isOn)}
|
|
751
786
|
/>
|
|
752
787
|
|
|
753
788
|
// File upload
|
|
754
|
-
<
|
|
789
|
+
<VFile
|
|
755
790
|
name="form.avatar"
|
|
756
791
|
isPreview // Show image preview
|
|
757
792
|
accept=".jpg,.png"
|
|
@@ -760,70 +795,70 @@ const [value, setValue] = useState('');
|
|
|
760
795
|
// FileCategory enum available for file categories
|
|
761
796
|
|
|
762
797
|
// File with base64 output
|
|
763
|
-
<
|
|
798
|
+
<VBase64File
|
|
764
799
|
name="form.file"
|
|
765
800
|
accept=".jpg,.jpeg,.png"
|
|
766
801
|
base64Image="iVBOR..." // Default base64 preview
|
|
767
802
|
/>
|
|
768
803
|
|
|
769
804
|
// Submit button
|
|
770
|
-
<
|
|
805
|
+
<VSubmit
|
|
771
806
|
caption="Submit"
|
|
772
|
-
fontSize={
|
|
773
|
-
backgroundColor={
|
|
774
|
-
frontColor={
|
|
807
|
+
fontSize={FontSizeType.Small}
|
|
808
|
+
backgroundColor={ColorType.Primary}
|
|
809
|
+
frontColor={ColorType.White}
|
|
775
810
|
/>
|
|
776
811
|
|
|
777
812
|
// Submit wrapper (wraps custom body with hidden submit input)
|
|
778
|
-
<
|
|
813
|
+
<VSubmitWrapper body={<button>Custom Submit UI</button>} />
|
|
779
814
|
```
|
|
780
815
|
|
|
781
816
|
### Media Components
|
|
782
817
|
|
|
783
818
|
```tsx
|
|
784
819
|
// Image
|
|
785
|
-
<
|
|
820
|
+
<VImage
|
|
786
821
|
src="/path/to/image.jpg"
|
|
787
822
|
alt="Description"
|
|
788
|
-
category={
|
|
823
|
+
category={ImageCategory.Circle} // Circle, Squared, FullSize, Scale
|
|
789
824
|
/>
|
|
790
825
|
|
|
791
826
|
// SVG (wraps imported SVG components)
|
|
792
827
|
import IconSvg from './icon.svg';
|
|
793
|
-
<
|
|
794
|
-
fontSize={
|
|
795
|
-
frontColor={
|
|
828
|
+
<VSvg
|
|
829
|
+
fontSize={FontSizeType.Large}
|
|
830
|
+
frontColor={ColorType.Primary}
|
|
796
831
|
>
|
|
797
832
|
<IconSvg />
|
|
798
|
-
</
|
|
833
|
+
</VSvg>
|
|
799
834
|
// SvgCategory enum available for SVG categories
|
|
800
835
|
|
|
801
836
|
// Background image
|
|
802
|
-
<
|
|
837
|
+
<VBackground
|
|
803
838
|
image="/path/to/bg.jpg"
|
|
804
839
|
imageWidth="100%"
|
|
805
840
|
imageHeight="400px"
|
|
806
|
-
position={
|
|
841
|
+
position={BackgroundPositionType.Center}
|
|
807
842
|
>
|
|
808
843
|
<OverlayContent />
|
|
809
|
-
</
|
|
844
|
+
</VBackground>
|
|
810
845
|
|
|
811
846
|
// Audio / Video
|
|
812
|
-
<
|
|
813
|
-
<
|
|
847
|
+
<VAudio src="/audio.mp3" />
|
|
848
|
+
<VVideo src="/video.mp4" />
|
|
814
849
|
```
|
|
815
850
|
|
|
816
851
|
### VTooltip
|
|
817
852
|
|
|
818
853
|
```tsx
|
|
819
854
|
// Tooltip uses Dock internally. Requires renderOverlay and dockCategory.
|
|
820
|
-
<
|
|
821
|
-
category={
|
|
822
|
-
dockCategory={
|
|
855
|
+
<VTooltip
|
|
856
|
+
category={TooltipCategory.Hover}
|
|
857
|
+
dockCategory={DockCategory.Top}
|
|
823
858
|
renderOverlay={() => <div>Tooltip content</div>}
|
|
824
859
|
>
|
|
825
860
|
<button>Hover me</button>
|
|
826
|
-
</
|
|
861
|
+
</VTooltip>
|
|
827
862
|
|
|
828
863
|
// TooltipCategory: Hover (default), Click
|
|
829
864
|
```
|
|
@@ -832,14 +867,14 @@ import IconSvg from './icon.svg';
|
|
|
832
867
|
|
|
833
868
|
```tsx
|
|
834
869
|
// Uses animate.css library. category is required.
|
|
835
|
-
<
|
|
836
|
-
category={
|
|
837
|
-
speed={
|
|
838
|
-
delay={
|
|
839
|
-
repeat={
|
|
870
|
+
<VAnimation
|
|
871
|
+
category={AnimationCategory.Bounce}
|
|
872
|
+
speed={AnimationSpeed.Fast}
|
|
873
|
+
delay={AnimationDelay.Delay1Second}
|
|
874
|
+
repeat={AnimationRepeat.Infinite}
|
|
840
875
|
>
|
|
841
876
|
<Content />
|
|
842
|
-
</
|
|
877
|
+
</VAnimation>
|
|
843
878
|
|
|
844
879
|
// AnimationCategory: Bounce, Flash, Pulse, RubberBand, ShakeX, Swing, Tada,
|
|
845
880
|
// Wobble, Jello, HeartBeat, FadeIn, FadeOut, ZoomIn, ZoomOut,
|
|
@@ -853,23 +888,23 @@ import IconSvg from './icon.svg';
|
|
|
853
888
|
### Shape Components
|
|
854
889
|
|
|
855
890
|
```tsx
|
|
856
|
-
<
|
|
891
|
+
<VEllipse width="100px" height="100px" backgroundColor={ColorType.Primary} />
|
|
857
892
|
// EllipseCategory enum available
|
|
858
893
|
|
|
859
|
-
<
|
|
894
|
+
<VRectangle width="200px" height="50px" backgroundColor={ColorType.Info} />
|
|
860
895
|
|
|
861
|
-
<
|
|
896
|
+
<VLine />
|
|
862
897
|
// LineCategory enum available
|
|
863
898
|
|
|
864
|
-
<
|
|
899
|
+
<VShadow category={ShadowCategory.Small}><Content /></VShadow>
|
|
865
900
|
```
|
|
866
901
|
|
|
867
902
|
### VTheme (Theme Provider)
|
|
868
903
|
|
|
869
904
|
```tsx
|
|
870
|
-
<
|
|
905
|
+
<VTheme category={ThemeCategory.Light}>
|
|
871
906
|
<App />
|
|
872
|
-
</
|
|
907
|
+
</VTheme>
|
|
873
908
|
|
|
874
909
|
// ThemeCategory: Light, Dark (or custom)
|
|
875
910
|
// ThemeVariables type available for typed CSS variable overrides
|
|
@@ -879,53 +914,53 @@ import IconSvg from './icon.svg';
|
|
|
879
914
|
|
|
880
915
|
```tsx
|
|
881
916
|
// VCard — structured card with head and body
|
|
882
|
-
<
|
|
883
|
-
head={<
|
|
884
|
-
body={<
|
|
917
|
+
<VCard
|
|
918
|
+
head={<VLabel caption="Card Title" />}
|
|
919
|
+
body={<VText caption="Card content" />}
|
|
885
920
|
isDraggable={false}
|
|
886
921
|
/>
|
|
887
922
|
|
|
888
923
|
// VCardMedia — card with media, head, body, foot sections
|
|
889
|
-
<
|
|
890
|
-
media={<
|
|
891
|
-
head={<
|
|
892
|
-
body={<
|
|
924
|
+
<VCardMedia
|
|
925
|
+
media={<VImage src="/image.jpg" category={ImageCategory.FullSize} />}
|
|
926
|
+
head={<VLabel caption="Title" />}
|
|
927
|
+
body={<VText caption="Description" />}
|
|
893
928
|
foot={<button>Action</button>}
|
|
894
929
|
/>
|
|
895
930
|
|
|
896
931
|
// VCardSocial — social media card variant
|
|
897
|
-
<
|
|
932
|
+
<VCardSocial ... />
|
|
898
933
|
|
|
899
934
|
// VCardWindow — card with background image
|
|
900
|
-
<
|
|
935
|
+
<VCardWindow
|
|
901
936
|
backgroundUrl="/bg.jpg"
|
|
902
|
-
backgroundSize={
|
|
937
|
+
backgroundSize={CardWindowSizeType.Cover}
|
|
903
938
|
>
|
|
904
939
|
<OverlayContent />
|
|
905
|
-
</
|
|
940
|
+
</VCardWindow>
|
|
906
941
|
|
|
907
942
|
// VBlock — structured block with icon, action, caption, subCaption
|
|
908
|
-
<
|
|
943
|
+
<VBlock
|
|
909
944
|
icon={<Icon />}
|
|
910
945
|
action={<button>Edit</button>}
|
|
911
|
-
caption={<
|
|
912
|
-
subCaption={<
|
|
946
|
+
caption={<VLabel caption="Title" />}
|
|
947
|
+
subCaption={<VLabel caption="Subtitle" />}
|
|
913
948
|
/>
|
|
914
949
|
|
|
915
950
|
// VStack — stacks children with z-index layering
|
|
916
|
-
<
|
|
951
|
+
<VStack>
|
|
917
952
|
<Layer1 />
|
|
918
953
|
<Layer2 />
|
|
919
|
-
</
|
|
954
|
+
</VStack>
|
|
920
955
|
|
|
921
956
|
// VTree — hierarchical tree view
|
|
922
|
-
<
|
|
957
|
+
<VTree nodes={treeData} />
|
|
923
958
|
// IVTreeNode type exported for tree node data structure
|
|
924
959
|
|
|
925
960
|
// VPhoto — background-image based photo with sizing
|
|
926
|
-
<
|
|
927
|
-
category={
|
|
928
|
-
position={
|
|
961
|
+
<VPhoto
|
|
962
|
+
category={PhotoCategory.Cover}
|
|
963
|
+
position={PhotoPositionType.Center}
|
|
929
964
|
src="/photo.jpg"
|
|
930
965
|
width="100%"
|
|
931
966
|
height="300px"
|
|
@@ -934,10 +969,10 @@ import IconSvg from './icon.svg';
|
|
|
934
969
|
// PhotoPositionType: Left, Center, Right
|
|
935
970
|
|
|
936
971
|
// VAvatar — user avatar display
|
|
937
|
-
<
|
|
972
|
+
<VAvatar ... />
|
|
938
973
|
|
|
939
974
|
// VDynamic — renders component by name from registry
|
|
940
|
-
<
|
|
975
|
+
<VDynamic
|
|
941
976
|
components={{ MyWidget: WidgetComponent, MyChart: ChartComponent }}
|
|
942
977
|
name="MyWidget"
|
|
943
978
|
customProp="value" // extra props are passed to the resolved component
|
|
@@ -949,39 +984,39 @@ import IconSvg from './icon.svg';
|
|
|
949
984
|
|
|
950
985
|
```tsx
|
|
951
986
|
// Debug utility component
|
|
952
|
-
<
|
|
987
|
+
<Debug ... />
|
|
953
988
|
|
|
954
989
|
// Google Font loader
|
|
955
|
-
<
|
|
956
|
-
type={
|
|
990
|
+
<VGoogleFont
|
|
991
|
+
type={GoogleFontType...}
|
|
957
992
|
...
|
|
958
993
|
/>
|
|
959
994
|
// GoogleFontType, IGoogleTypeface, IGoogleFont types available
|
|
960
995
|
|
|
961
996
|
// Chrome extension validation
|
|
962
|
-
<
|
|
997
|
+
<VChromeExtensionValidator ... />
|
|
963
998
|
// ExtensionStatus enum exported
|
|
964
999
|
|
|
965
1000
|
// Auth components
|
|
966
|
-
<
|
|
967
|
-
category={
|
|
968
|
-
uxMode={
|
|
1001
|
+
<GoogleGrant
|
|
1002
|
+
category={GoogleGrantCategory.Implicit}
|
|
1003
|
+
uxMode={GoogleGrantUXMode.Popup}
|
|
969
1004
|
...
|
|
970
1005
|
/>
|
|
971
1006
|
// GoogleGrantCategory: Implicit, AuthorizationCode
|
|
972
1007
|
// GoogleGrantUXMode: Popup, Redirect
|
|
973
1008
|
// GoogleGrantCode, GoogleGrantToken types exported
|
|
974
1009
|
|
|
975
|
-
<
|
|
976
|
-
uxMode={
|
|
1010
|
+
<GoogleSignin
|
|
1011
|
+
uxMode={GoogleSigninUXMode...}
|
|
977
1012
|
...
|
|
978
1013
|
/>
|
|
979
1014
|
|
|
980
|
-
<
|
|
981
|
-
<
|
|
1015
|
+
<FigmaSignin ... />
|
|
1016
|
+
<WeComSignin ... />
|
|
982
1017
|
|
|
983
1018
|
// JWT utility
|
|
984
|
-
|
|
1019
|
+
parseJWT(token) // returns IUserProfile
|
|
985
1020
|
// IUserProfile type exported
|
|
986
1021
|
```
|
|
987
1022
|
|
|
@@ -989,32 +1024,34 @@ Den.Components.parseJWT(token) // returns IUserProfile
|
|
|
989
1024
|
|
|
990
1025
|
```tsx
|
|
991
1026
|
// Semantic HTML wrappers
|
|
992
|
-
<
|
|
993
|
-
<
|
|
994
|
-
<
|
|
995
|
-
<
|
|
996
|
-
<
|
|
1027
|
+
<VHeader>...</VHeader>
|
|
1028
|
+
<VNav>...</VNav>
|
|
1029
|
+
<VMain>...</VMain>
|
|
1030
|
+
<VAside>...</VAside>
|
|
1031
|
+
<VFooter>...</VFooter>
|
|
1032
|
+
<VSection>...</VSection>
|
|
1033
|
+
<VHR />
|
|
997
1034
|
|
|
998
1035
|
// Mask overlay
|
|
999
|
-
<
|
|
1036
|
+
<VMask><Content /></VMask>
|
|
1000
1037
|
|
|
1001
1038
|
// Iframe
|
|
1002
|
-
<
|
|
1039
|
+
<VFrame src="https://example.com" />
|
|
1003
1040
|
|
|
1004
1041
|
// Loading indicator
|
|
1005
|
-
<
|
|
1042
|
+
<VLoading />
|
|
1006
1043
|
|
|
1007
1044
|
// Error boundary
|
|
1008
|
-
<
|
|
1045
|
+
<VErrorBoundary>
|
|
1009
1046
|
<RiskyComponent />
|
|
1010
|
-
</
|
|
1047
|
+
</VErrorBoundary>
|
|
1011
1048
|
```
|
|
1012
1049
|
|
|
1013
1050
|
### Utility Functions (core)
|
|
1014
1051
|
|
|
1015
1052
|
```tsx
|
|
1016
1053
|
// Convert FormData to nested JSON (used internally by VForm)
|
|
1017
|
-
|
|
1054
|
+
convertFormDataToJson(formData)
|
|
1018
1055
|
```
|
|
1019
1056
|
|
|
1020
1057
|
---
|
|
@@ -1026,9 +1063,9 @@ Den.Components.convertFormDataToJson(formData)
|
|
|
1026
1063
|
Before using network features, initialize the bootstrap:
|
|
1027
1064
|
|
|
1028
1065
|
```tsx
|
|
1029
|
-
import {
|
|
1066
|
+
import { ... } from '@fewbox/den-app';
|
|
1030
1067
|
|
|
1031
|
-
|
|
1068
|
+
boot({
|
|
1032
1069
|
getToken: () => localStorage.getItem('token') || '',
|
|
1033
1070
|
getAppSettings: () => ({
|
|
1034
1071
|
endpoint: {
|
|
@@ -1054,9 +1091,9 @@ Den.FewBox.boot({
|
|
|
1054
1091
|
});
|
|
1055
1092
|
|
|
1056
1093
|
// Or use the Boot component:
|
|
1057
|
-
<
|
|
1094
|
+
<Boot options={bootOptions} />
|
|
1058
1095
|
|
|
1059
|
-
// Types exported
|
|
1096
|
+
// Types exported:
|
|
1060
1097
|
// IFewBoxOptions, IAppSettings, IEndpoint, IError, BootClass
|
|
1061
1098
|
```
|
|
1062
1099
|
|
|
@@ -1065,21 +1102,21 @@ Den.FewBox.boot({
|
|
|
1065
1102
|
All Fetch clients return RxJS Observables for use in Redux Observable epics:
|
|
1066
1103
|
|
|
1067
1104
|
```tsx
|
|
1068
|
-
import {
|
|
1105
|
+
import { ... } from '@fewbox/den-app';
|
|
1069
1106
|
|
|
1070
1107
|
// Default endpoint (uses app settings endpoint)
|
|
1071
|
-
new
|
|
1072
|
-
new
|
|
1073
|
-
new
|
|
1074
|
-
new
|
|
1075
|
-
new
|
|
1108
|
+
new GetFetch('/users', (payload) => ({ type: 'USERS_LOADED', payload }));
|
|
1109
|
+
new PostFetch('/users', body, (payload) => ({ type: 'USER_CREATED', payload }));
|
|
1110
|
+
new PutFetch('/users/1', body, processAction);
|
|
1111
|
+
new PatchFetch('/users/1', body, processAction);
|
|
1112
|
+
new DeleteFetch('/users/1', processAction);
|
|
1076
1113
|
|
|
1077
1114
|
// External endpoint (bypasses app settings, uses named endpoint from appSettings)
|
|
1078
|
-
new
|
|
1079
|
-
new
|
|
1080
|
-
new
|
|
1081
|
-
new
|
|
1082
|
-
new
|
|
1115
|
+
new GetFetchExternal('externalService', '/data', processAction);
|
|
1116
|
+
new PostFetchExternal('externalService', '/data', body, processAction);
|
|
1117
|
+
new PutFetchExternal('externalService', '/data/1', body, processAction);
|
|
1118
|
+
new PatchFetchExternal('externalService', '/data/1', body, processAction);
|
|
1119
|
+
new DeleteFetchExternal('externalService', '/data/1', processAction);
|
|
1083
1120
|
```
|
|
1084
1121
|
|
|
1085
1122
|
### AJAX-based HTTP Clients
|
|
@@ -1088,43 +1125,43 @@ RxJS Ajax-based clients (alternative to Fetch):
|
|
|
1088
1125
|
|
|
1089
1126
|
```tsx
|
|
1090
1127
|
// Default endpoint
|
|
1091
|
-
new
|
|
1092
|
-
new
|
|
1093
|
-
new
|
|
1094
|
-
new
|
|
1095
|
-
new
|
|
1128
|
+
new Get('/users', processAction);
|
|
1129
|
+
new Post('/users', body, processAction);
|
|
1130
|
+
new Put('/users/1', body, processAction);
|
|
1131
|
+
new Patch('/users/1', body, processAction);
|
|
1132
|
+
new Delete('/users/1', processAction);
|
|
1096
1133
|
|
|
1097
1134
|
// External endpoint
|
|
1098
|
-
new
|
|
1099
|
-
new
|
|
1100
|
-
new
|
|
1101
|
-
new
|
|
1102
|
-
new
|
|
1135
|
+
new GetExternal('externalService', '/data', processAction);
|
|
1136
|
+
new PostExternal('externalService', '/data', body, processAction);
|
|
1137
|
+
new PutExternal('externalService', '/data/1', body, processAction);
|
|
1138
|
+
new PatchExternal('externalService', '/data/1', body, processAction);
|
|
1139
|
+
new DeleteExternal('externalService', '/data/1', processAction);
|
|
1103
1140
|
|
|
1104
1141
|
// Text response variants (returns text instead of JSON)
|
|
1105
|
-
new
|
|
1106
|
-
new
|
|
1107
|
-
new
|
|
1108
|
-
new
|
|
1109
|
-
new
|
|
1142
|
+
new GetText('/data', processAction);
|
|
1143
|
+
new PostText('/data', body, processAction);
|
|
1144
|
+
new PutText('/data', body, processAction);
|
|
1145
|
+
new PatchText('/data', body, processAction);
|
|
1146
|
+
new DeleteText('/data', processAction);
|
|
1110
1147
|
// External text variants: GetTextExternal, PostTextExternal, PutTextExternal, PatchTextExternal, DeleteTextExternal
|
|
1111
1148
|
|
|
1112
1149
|
// Local storage
|
|
1113
|
-
new
|
|
1150
|
+
new GetLocal('/local-path', processAction);
|
|
1114
1151
|
```
|
|
1115
1152
|
|
|
1116
1153
|
### GraphQL
|
|
1117
1154
|
|
|
1118
1155
|
```tsx
|
|
1119
1156
|
// Default endpoint
|
|
1120
|
-
new
|
|
1157
|
+
new GQL({ query: 'query { users { id name } }' }, processAction);
|
|
1121
1158
|
|
|
1122
1159
|
// External endpoint
|
|
1123
|
-
new
|
|
1160
|
+
new GQLExternal('externalService', { query: 'mutation { ... }' }, processAction);
|
|
1124
1161
|
|
|
1125
1162
|
// File upload
|
|
1126
|
-
new
|
|
1127
|
-
new
|
|
1163
|
+
new GQLUpload({ query: '...', variables: { file } }, processAction);
|
|
1164
|
+
new GQLExternalUpload('externalService', { query: '...' }, processAction);
|
|
1128
1165
|
|
|
1129
1166
|
// IGraphQL type available for query/mutation objects
|
|
1130
1167
|
```
|
|
@@ -1132,17 +1169,17 @@ new Den.Network.GQLExternalUpload('externalService', { query: '...' }, processAc
|
|
|
1132
1169
|
### Server-Sent Events (SSE)
|
|
1133
1170
|
|
|
1134
1171
|
```tsx
|
|
1135
|
-
new
|
|
1136
|
-
new
|
|
1137
|
-
new
|
|
1138
|
-
new
|
|
1172
|
+
new GetSSE('/events', processAction);
|
|
1173
|
+
new PostSSE('/events', processAction);
|
|
1174
|
+
new GetSSEExternal('externalService', '/events', processAction);
|
|
1175
|
+
new PostSSEExternal('externalService', '/events', processAction);
|
|
1139
1176
|
```
|
|
1140
1177
|
|
|
1141
1178
|
### WebSocket
|
|
1142
1179
|
|
|
1143
1180
|
```tsx
|
|
1144
|
-
new
|
|
1145
|
-
//
|
|
1181
|
+
new WS({ url: 'wss://example.com/ws' });
|
|
1182
|
+
// ws() function also available
|
|
1146
1183
|
// IWebsocketOptions type exported
|
|
1147
1184
|
```
|
|
1148
1185
|
|
|
@@ -1152,18 +1189,18 @@ For use outside Redux Observable epics:
|
|
|
1152
1189
|
|
|
1153
1190
|
```tsx
|
|
1154
1191
|
// Default endpoint
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1192
|
+
verbsGetPromise('/users');
|
|
1193
|
+
verbsPostPromise('/users', body);
|
|
1194
|
+
verbsPutPromise('/users/1', body);
|
|
1195
|
+
verbsPatchPromise('/users/1', body);
|
|
1196
|
+
verbsDeletePromise('/users/1');
|
|
1160
1197
|
|
|
1161
1198
|
// External endpoint
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1199
|
+
verbsGetPromiseExternal('externalService', '/data');
|
|
1200
|
+
verbsPostPromiseExternal('externalService', '/data', body);
|
|
1201
|
+
verbsPutPromiseExternal('externalService', '/data/1', body);
|
|
1202
|
+
verbsPatchPromiseExternal('externalService', '/data/1', body);
|
|
1203
|
+
verbsDeletePromiseExternal('externalService', '/data/1');
|
|
1167
1204
|
```
|
|
1168
1205
|
|
|
1169
1206
|
### Raw HTTP Verb Functions
|
|
@@ -1180,14 +1217,14 @@ Low-level verb functions that return Observables:
|
|
|
1180
1217
|
### Network Utilities
|
|
1181
1218
|
|
|
1182
1219
|
```tsx
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1220
|
+
buildHeaders(customHeaders); // Merge custom headers with JWT token
|
|
1221
|
+
buildUrl(path); // Build URL from app settings endpoint
|
|
1222
|
+
buildExternalUrl(externalName, path); // Build URL from named external endpoint
|
|
1223
|
+
JsonHeaders; // Default JSON content-type headers
|
|
1224
|
+
parseAjaxData(response); // Parse AJAX response
|
|
1225
|
+
parseFetchData(response); // Parse Fetch response
|
|
1226
|
+
parseGQLAjaxData(response); // Parse GraphQL response
|
|
1227
|
+
convertJsonToGraphQLSchema(json); // Convert JSON to GraphQL schema string
|
|
1191
1228
|
```
|
|
1192
1229
|
|
|
1193
1230
|
### Redux Observable Epic Pattern
|
|
@@ -1200,7 +1237,7 @@ const fetchUsersEpic = (action$) =>
|
|
|
1200
1237
|
action$.pipe(
|
|
1201
1238
|
ofType('FETCH_USERS'),
|
|
1202
1239
|
switchMap(() =>
|
|
1203
|
-
new
|
|
1240
|
+
new GetFetch('/users', (payload) => ({
|
|
1204
1241
|
type: 'USERS_LOADED',
|
|
1205
1242
|
payload
|
|
1206
1243
|
}))
|
|
@@ -1221,20 +1258,20 @@ const fetchUsersEpic = (action$) =>
|
|
|
1221
1258
|
Type definitions for Redux store integration:
|
|
1222
1259
|
|
|
1223
1260
|
```tsx
|
|
1224
|
-
import {
|
|
1261
|
+
import { ... } from '@fewbox/den-app';
|
|
1225
1262
|
|
|
1226
1263
|
// Pagination
|
|
1227
|
-
type IList =
|
|
1228
|
-
type IPaging =
|
|
1229
|
-
type IContinuePaging =
|
|
1264
|
+
type IList = IList; // List response wrapper
|
|
1265
|
+
type IPaging = IPaging; // Paged list with page/size
|
|
1266
|
+
type IContinuePaging = IContinuePaging; // Cursor-based pagination
|
|
1230
1267
|
|
|
1231
1268
|
// Data types
|
|
1232
|
-
type Json =
|
|
1233
|
-
type EnumDictionary<K, V> =
|
|
1269
|
+
type Json = Json; // Generic JSON type
|
|
1270
|
+
type EnumDictionary<K, V> = EnumDictionary<K, V>; // Enum-keyed dictionary
|
|
1234
1271
|
|
|
1235
1272
|
// Response wrappers
|
|
1236
|
-
type IMetaResponse =
|
|
1237
|
-
type IPayloadResponse =
|
|
1273
|
+
type IMetaResponse = IMetaResponse; // Response with metadata
|
|
1274
|
+
type IPayloadResponse = IPayloadResponse; // Response with payload
|
|
1238
1275
|
```
|
|
1239
1276
|
|
|
1240
1277
|
---
|
|
@@ -1244,18 +1281,18 @@ type IPayloadResponse = Den.Store.IPayloadResponse; // Response with payload
|
|
|
1244
1281
|
Internationalization utilities:
|
|
1245
1282
|
|
|
1246
1283
|
```tsx
|
|
1247
|
-
import {
|
|
1284
|
+
import { ... } from '@fewbox/den-app';
|
|
1248
1285
|
|
|
1249
1286
|
// Get browser language
|
|
1250
|
-
|
|
1251
|
-
|
|
1287
|
+
getBrowserLang(); // "en" (short code)
|
|
1288
|
+
getBrowserLangFull(); // "en-US" (full code)
|
|
1252
1289
|
|
|
1253
1290
|
// Get formatted intl message (uses BootClass language config)
|
|
1254
|
-
|
|
1291
|
+
getIntlMessage('Hello.World', 'en', { name: 'World' });
|
|
1255
1292
|
|
|
1256
1293
|
// Select messages for a locale from a locales object
|
|
1257
|
-
const messages =
|
|
1258
|
-
const messagesFull =
|
|
1294
|
+
const messages = language(locales, 'en');
|
|
1295
|
+
const messagesFull = languageFull(locales, 'en-US');
|
|
1259
1296
|
```
|
|
1260
1297
|
|
|
1261
1298
|
---
|
|
@@ -1296,114 +1333,114 @@ RightTop, RightBottom, LeftTop, LeftBottom, TopBottom, LeftRight
|
|
|
1296
1333
|
### Page Layout (header + content + footer)
|
|
1297
1334
|
|
|
1298
1335
|
```tsx
|
|
1299
|
-
<
|
|
1300
|
-
<
|
|
1336
|
+
<Y height="100vh">
|
|
1337
|
+
<VBoundary padding="1em" backgroundColor={ColorType.Primary}>
|
|
1301
1338
|
<Header />
|
|
1302
|
-
</
|
|
1303
|
-
<
|
|
1339
|
+
</VBoundary>
|
|
1340
|
+
<VBoundary selfGrow={1} overflow="auto" padding="1em">
|
|
1304
1341
|
<MainContent />
|
|
1305
|
-
</
|
|
1306
|
-
<
|
|
1342
|
+
</VBoundary>
|
|
1343
|
+
<VBoundary padding="1em" backgroundColor={ColorType.Dark}>
|
|
1307
1344
|
<Footer />
|
|
1308
|
-
</
|
|
1309
|
-
</
|
|
1345
|
+
</VBoundary>
|
|
1346
|
+
</Y>
|
|
1310
1347
|
```
|
|
1311
1348
|
|
|
1312
1349
|
### Centered Content
|
|
1313
1350
|
|
|
1314
1351
|
```tsx
|
|
1315
|
-
<
|
|
1316
|
-
<
|
|
1317
|
-
</
|
|
1352
|
+
<XCenter height="100%">
|
|
1353
|
+
<SCenter><Content /></SCenter>
|
|
1354
|
+
</XCenter>
|
|
1318
1355
|
```
|
|
1319
1356
|
|
|
1320
1357
|
### Sidebar Layout
|
|
1321
1358
|
|
|
1322
1359
|
```tsx
|
|
1323
|
-
<
|
|
1324
|
-
<
|
|
1360
|
+
<X height="100vh">
|
|
1361
|
+
<VBoundary width="250px" backgroundColor={ColorType.Dark}>
|
|
1325
1362
|
<Sidebar />
|
|
1326
|
-
</
|
|
1327
|
-
<
|
|
1328
|
-
</
|
|
1363
|
+
</VBoundary>
|
|
1364
|
+
<VBoundary selfGrow={1}><MainContent /></VBoundary>
|
|
1365
|
+
</X>
|
|
1329
1366
|
```
|
|
1330
1367
|
|
|
1331
1368
|
### Sticky Navigation Bar
|
|
1332
1369
|
|
|
1333
1370
|
```tsx
|
|
1334
|
-
<
|
|
1335
|
-
<
|
|
1336
|
-
<
|
|
1337
|
-
<
|
|
1338
|
-
<
|
|
1339
|
-
<
|
|
1340
|
-
</
|
|
1341
|
-
</
|
|
1342
|
-
</
|
|
1371
|
+
<Position category={PositionCategory.Edge} top="0px" isFullWidth zIndex={10}>
|
|
1372
|
+
<XBetween height="48px" padding="0 1em" backgroundColor={ColorType.Primary}>
|
|
1373
|
+
<VLabel caption="Logo" frontColor={ColorType.White} />
|
|
1374
|
+
<XRight gap="1em">
|
|
1375
|
+
<VHyperlink category={HyperlinkCategory.Self} to="/about">About</VHyperlink>
|
|
1376
|
+
<VHyperlink category={HyperlinkCategory.Self} to="/contact">Contact</VHyperlink>
|
|
1377
|
+
</XRight>
|
|
1378
|
+
</XBetween>
|
|
1379
|
+
</Position>
|
|
1343
1380
|
```
|
|
1344
1381
|
|
|
1345
1382
|
### Form with Validation
|
|
1346
1383
|
|
|
1347
1384
|
```tsx
|
|
1348
|
-
<
|
|
1385
|
+
<VForm
|
|
1349
1386
|
handleSubmit={(data) => api.login(data.form)}
|
|
1350
1387
|
handleValidateError={(invalidInputs) => { invalidInputs[0]?.focus(); }}>
|
|
1351
|
-
<
|
|
1352
|
-
<
|
|
1353
|
-
<
|
|
1354
|
-
<
|
|
1355
|
-
frontColor={
|
|
1356
|
-
</
|
|
1357
|
-
</
|
|
1388
|
+
<Y gap="1em" padding="2em">
|
|
1389
|
+
<VEmail name="form.email" required placeholder="Email" label="Email" />
|
|
1390
|
+
<VPassword name="form.password" required minLength={8} placeholder="Password" label="Password" />
|
|
1391
|
+
<VSubmit caption="Sign In" backgroundColor={ColorType.Primary}
|
|
1392
|
+
frontColor={ColorType.White} borderRadius="0.5em" padding="0.8em 2em" />
|
|
1393
|
+
</Y>
|
|
1394
|
+
</VForm>
|
|
1358
1395
|
```
|
|
1359
1396
|
|
|
1360
1397
|
### Card Grid (app variant)
|
|
1361
1398
|
|
|
1362
1399
|
```tsx
|
|
1363
|
-
<
|
|
1400
|
+
<XWrapEvenly gap="1em" padding="1em">
|
|
1364
1401
|
{items.map(item => (
|
|
1365
|
-
<
|
|
1402
|
+
<VCardMedia
|
|
1366
1403
|
key={item.id}
|
|
1367
1404
|
width="300px"
|
|
1368
1405
|
borderRadius="0.5em"
|
|
1369
|
-
borderColor={
|
|
1406
|
+
borderColor={ColorType.Border}
|
|
1370
1407
|
borderStyle="solid"
|
|
1371
1408
|
borderWidth="1px"
|
|
1372
|
-
media={<
|
|
1373
|
-
head={<
|
|
1374
|
-
body={<
|
|
1409
|
+
media={<VImage src={item.image} category={ImageCategory.FullSize} />}
|
|
1410
|
+
head={<VLabel category={LabelCategory.H3} caption={item.title} />}
|
|
1411
|
+
body={<VText caption={item.description} />}
|
|
1375
1412
|
/>
|
|
1376
1413
|
))}
|
|
1377
|
-
</
|
|
1414
|
+
</XWrapEvenly>
|
|
1378
1415
|
```
|
|
1379
1416
|
|
|
1380
1417
|
### Absolute Positioning Inside Container
|
|
1381
1418
|
|
|
1382
1419
|
```tsx
|
|
1383
|
-
<
|
|
1384
|
-
<
|
|
1385
|
-
<
|
|
1420
|
+
<PositionArea category={PositionAreaCategory.FullSize}>
|
|
1421
|
+
<VBoundary height="300px" backgroundColor={ColorType.Dark}>
|
|
1422
|
+
<Position category={PositionCategory.Area} type={PositionType.LeftTop}>
|
|
1386
1423
|
<TopLeftContent />
|
|
1387
|
-
</
|
|
1388
|
-
<
|
|
1424
|
+
</Position>
|
|
1425
|
+
<Position category={PositionCategory.Area} type={PositionType.Center}>
|
|
1389
1426
|
<CenterContent />
|
|
1390
|
-
</
|
|
1391
|
-
</
|
|
1392
|
-
</
|
|
1427
|
+
</Position>
|
|
1428
|
+
</VBoundary>
|
|
1429
|
+
</PositionArea>
|
|
1393
1430
|
```
|
|
1394
1431
|
|
|
1395
1432
|
### Responsive Layout
|
|
1396
1433
|
|
|
1397
1434
|
```tsx
|
|
1398
|
-
<
|
|
1399
|
-
breakpointType={
|
|
1400
|
-
desktop={<
|
|
1435
|
+
<Responsive
|
|
1436
|
+
breakpointType={ScreenSizeType.Medium}
|
|
1437
|
+
desktop={<X gap="1em">
|
|
1401
1438
|
<Sidebar />
|
|
1402
1439
|
<MainContent />
|
|
1403
|
-
</
|
|
1404
|
-
mobile={<
|
|
1440
|
+
</X>}
|
|
1441
|
+
mobile={<Y gap="1em">
|
|
1405
1442
|
<MainContent />
|
|
1406
|
-
</
|
|
1443
|
+
</Y>}
|
|
1407
1444
|
/>
|
|
1408
1445
|
```
|
|
1409
1446
|
|