@dynamic-framework/ui-react 2.4.0 → 2.5.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.
- package/dist/css/dynamic-ui.css +14168 -7314
- package/dist/css/dynamic-ui.min.css +2 -2
- package/dist/index.esm.js +89 -25
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +88 -25
- package/dist/index.js.map +1 -1
- package/dist/types/components/DDropdown/DDropdown.d.ts +2 -1
- package/dist/types/components/DLayout/DLayout.d.ts +8 -9
- package/dist/types/components/DLayout/index.d.ts +1 -0
- package/dist/types/components/DToastContainer/DToastContainer.d.ts +39 -2
- package/dist/types/components/DToastContainer/index.d.ts +2 -0
- package/dist/types/components/DToastContainer/useDToast.d.ts +38 -5
- package/dist/types/components/index.d.ts +2 -0
- package/dist/types/components/interface.d.ts +1 -1
- package/dist/types/contexts/DContext.d.ts +67 -9
- package/dist/types/contexts/DPortalContext.d.ts +66 -8
- package/dist/types/contexts/index.d.ts +1 -1
- package/dist/types/hooks/index.d.ts +0 -1
- package/dist/types/hooks/usePortal.d.ts +6 -0
- package/package.json +4 -3
- package/src/style/abstracts/_mixins.scss +46 -0
- package/src/style/abstracts/_utilities.scss +1 -1
- package/src/style/abstracts/variables/_dropdowns.scss +18 -8
- package/src/style/base/_buttons.scss +4 -0
- package/src/style/base/_dropdown.scss +5 -16
- package/src/style/base/_toast.scss +18 -16
- package/src/style/root/_root.scss +26 -0
package/dist/index.esm.js
CHANGED
|
@@ -73,6 +73,12 @@ function useDisableBodyScrollEffect(disable) {
|
|
|
73
73
|
}, [disable]);
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
+
/**
|
|
77
|
+
* @internal
|
|
78
|
+
* Creates a DOM `<div>` portal mount point and appends it to `document.body`.
|
|
79
|
+
* This hook is used exclusively by `DPortalContextProvider` and is **not** part
|
|
80
|
+
* of the public API. Use `useDPortalContext` instead.
|
|
81
|
+
*/
|
|
76
82
|
function usePortal(portalName) {
|
|
77
83
|
const [hasPortal, setHasPortal] = useState(false);
|
|
78
84
|
useEffect(() => {
|
|
@@ -139,20 +145,22 @@ function DPortalContextProvider({ portalName, children, availablePortals, }) {
|
|
|
139
145
|
const { created } = usePortal(portalName);
|
|
140
146
|
const [stack, { push, pop, isEmpty }] = useStackState([]);
|
|
141
147
|
useDisableBodyScrollEffect(Boolean(stack.length));
|
|
142
|
-
const openPortal = useCallback(
|
|
148
|
+
const openPortal = useCallback(
|
|
149
|
+
// eslint-disable-next-line prefer-arrow-callback
|
|
150
|
+
function openPortalImpl(name, payload) {
|
|
143
151
|
var _a;
|
|
144
152
|
if (!availablePortals) {
|
|
145
|
-
throw new Error(
|
|
153
|
+
throw new Error('openPortal was called but DContextProvider has no availablePortals configured. '
|
|
154
|
+
+ 'Pass an availablePortals map to DContextProvider.');
|
|
146
155
|
}
|
|
147
156
|
const Component = availablePortals[name];
|
|
148
157
|
if (!Component) {
|
|
149
|
-
throw new Error(`
|
|
158
|
+
throw new Error(`No component registered for portal "${String(name)}". `
|
|
159
|
+
+ `Ensure "${String(name)}" has an entry in the availablePortals map on DContextProvider.`);
|
|
150
160
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
payload,
|
|
155
|
-
});
|
|
161
|
+
// K is a specific member of keyof T & string so the object satisfies
|
|
162
|
+
// InternalStackItem<T>, but TS can't verify generic-over-union assignability.
|
|
163
|
+
push({ name, Component, payload });
|
|
156
164
|
(_a = document.activeElement) === null || _a === void 0 ? void 0 : _a.blur();
|
|
157
165
|
}, [availablePortals, push]);
|
|
158
166
|
const closePortal = useCallback(() => {
|
|
@@ -161,11 +169,12 @@ function DPortalContextProvider({ portalName, children, availablePortals, }) {
|
|
|
161
169
|
}
|
|
162
170
|
pop();
|
|
163
171
|
}, [isEmpty, pop]);
|
|
172
|
+
const publicStack = useMemo(() => stack.map(({ name, payload }) => ({ name, payload })), [stack]);
|
|
164
173
|
const value = useMemo(() => ({
|
|
165
|
-
stack,
|
|
174
|
+
stack: publicStack,
|
|
166
175
|
openPortal,
|
|
167
176
|
closePortal,
|
|
168
|
-
}), [
|
|
177
|
+
}), [publicStack, openPortal, closePortal]);
|
|
169
178
|
const handleClose = useCallback((target) => {
|
|
170
179
|
if (!(target instanceof HTMLDivElement)) {
|
|
171
180
|
return;
|
|
@@ -221,10 +230,31 @@ function DPortalContextProvider({ portalName, children, availablePortals, }) {
|
|
|
221
230
|
jsx(Component, { name: name, payload: payload }, name),
|
|
222
231
|
]) }) }), document.getElementById(portalName))] }));
|
|
223
232
|
}
|
|
233
|
+
/**
|
|
234
|
+
* Hook to open/close registered portals (modals, offcanvas, etc.).
|
|
235
|
+
*
|
|
236
|
+
* **Prerequisite**: must be called inside a `DContextProvider` configured with
|
|
237
|
+
* `portalName` and `availablePortals`. `DContextProvider` mounts
|
|
238
|
+
* `DPortalContextProvider` internally — consumers never use
|
|
239
|
+
* `DPortalContextProvider` directly.
|
|
240
|
+
*
|
|
241
|
+
* @template T - Map of portal name → payload shape (e.g. `ModalPayloads`).
|
|
242
|
+
* Typing this generic gives you autocomplete on `openPortal` arguments.
|
|
243
|
+
* @returns `{ openPortal, closePortal, stack }` from the nearest portal context.
|
|
244
|
+
* @throws If called outside of `DContextProvider` / `DPortalContextProvider`.
|
|
245
|
+
*
|
|
246
|
+
* @requires DContextProvider
|
|
247
|
+
*
|
|
248
|
+
* @example
|
|
249
|
+
* ```tsx
|
|
250
|
+
* const { openPortal, closePortal } = useDPortalContext<ModalPayloads>();
|
|
251
|
+
* openPortal('confirm', { message: 'Are you sure?' });
|
|
252
|
+
* ```
|
|
253
|
+
*/
|
|
224
254
|
function useDPortalContext() {
|
|
225
255
|
const context = useContext(DPortalContext);
|
|
226
256
|
if (context === undefined) {
|
|
227
|
-
throw new Error('
|
|
257
|
+
throw new Error('useDPortalContext was used outside of DPortalContextProvider');
|
|
228
258
|
}
|
|
229
259
|
return context;
|
|
230
260
|
}
|
|
@@ -280,10 +310,17 @@ const DEFAULT_STATE = {
|
|
|
280
310
|
xxl: '',
|
|
281
311
|
},
|
|
282
312
|
setContext: () => { },
|
|
283
|
-
portalName: 'd-portal',
|
|
284
313
|
};
|
|
285
314
|
const DContext = createContext(DEFAULT_STATE);
|
|
286
|
-
|
|
315
|
+
/**
|
|
316
|
+
* Root context provider for Dynamic UI. Wrap your application with this
|
|
317
|
+
* component to configure icons, currency, language, and portal settings
|
|
318
|
+
* for all descendant Dynamic UI components.
|
|
319
|
+
*
|
|
320
|
+
* @template T - Map of portal name → payload shape (e.g. `{ modal: { title: string } }`).
|
|
321
|
+
* Pass it once at the top level: `<DContextProvider<MyPortals> ...>`.
|
|
322
|
+
*/
|
|
323
|
+
function DContextProvider({ language = DEFAULT_STATE.language, currency = DEFAULT_STATE.currency, icon = DEFAULT_STATE.icon, iconMap = DEFAULT_STATE.iconMap, portalName = 'd-portal', availablePortals, children, }) {
|
|
287
324
|
const [internalContext, setInternalContext,] = useState({
|
|
288
325
|
language,
|
|
289
326
|
currency,
|
|
@@ -307,12 +344,14 @@ function DContextProvider({ language = DEFAULT_STATE.language, currency = DEFAUL
|
|
|
307
344
|
const value = useMemo(() => (Object.assign(Object.assign({}, internalContext), { setContext })), [internalContext, setContext]);
|
|
308
345
|
return (jsx(DContext.Provider, { value: value, children: jsx(DPortalContextProvider, { portalName: portalName, availablePortals: availablePortals, children: children }) }));
|
|
309
346
|
}
|
|
347
|
+
/**
|
|
348
|
+
* Returns the Dynamic UI context value set by `DContextProvider`.
|
|
349
|
+
* Falls back to the library's built-in defaults when no `DContextProvider`
|
|
350
|
+
* is present in the tree — wrap your application with `DContextProvider`
|
|
351
|
+
* to customise icons, currency, language, and portal settings.
|
|
352
|
+
*/
|
|
310
353
|
function useDContext() {
|
|
311
|
-
|
|
312
|
-
if (context === undefined) {
|
|
313
|
-
throw new Error('useDContext was used outside of DContextProvider');
|
|
314
|
-
}
|
|
315
|
-
return context;
|
|
354
|
+
return useContext(DContext);
|
|
316
355
|
}
|
|
317
356
|
|
|
318
357
|
function subscribeToMediaQuery(query, callback) {
|
|
@@ -2379,12 +2418,34 @@ var DToast$1 = Object.assign(DToast, {
|
|
|
2379
2418
|
Body: DToastBody,
|
|
2380
2419
|
});
|
|
2381
2420
|
|
|
2382
|
-
function DToastContainer({ containerClassName, position = 'bottom-center', reverseOrder = false, containerStyle, toastOptions, gutter, }) {
|
|
2421
|
+
function DToastContainer({ containerClassName, position = 'bottom-center', reverseOrder = false, containerStyle, toastOptions, gutter = 8, }) {
|
|
2383
2422
|
return (jsx(Toaster, { containerClassName: containerClassName, position: position, reverseOrder: reverseOrder, containerStyle: containerStyle, gutter: gutter, toastOptions: toastOptions }));
|
|
2384
2423
|
}
|
|
2385
2424
|
|
|
2425
|
+
/**
|
|
2426
|
+
* Hook that provides a `toast` function to dispatch DToast notifications.
|
|
2427
|
+
*
|
|
2428
|
+
* Prerequisites:
|
|
2429
|
+
* - The calling component must be inside `DContextProvider` (provides icon context).
|
|
2430
|
+
* - `DToastContainer` must be present somewhere in the component tree as a render target.
|
|
2431
|
+
*
|
|
2432
|
+
* @returns {{ toast }} Object containing a `toast` dispatcher function.
|
|
2433
|
+
* @requires DContextProvider
|
|
2434
|
+
* @requires DToastContainer
|
|
2435
|
+
* @example
|
|
2436
|
+
* const { toast } = useDToast();
|
|
2437
|
+
* toast({ title: 'Saved', color: 'success' });
|
|
2438
|
+
*/
|
|
2386
2439
|
function useDToast() {
|
|
2387
2440
|
const { iconMap: { xLg, }, } = useDContext();
|
|
2441
|
+
/**
|
|
2442
|
+
* Dispatches a toast notification rendered as a `DToast` component.
|
|
2443
|
+
* When `data` is a `ToastData` object, the default DToast layout is used.
|
|
2444
|
+
* When `data` is a render function, full custom content is rendered instead.
|
|
2445
|
+
* Returns the toast ID, which can be passed to `reactHotToast.dismiss(id)`.
|
|
2446
|
+
* @param data - Toast content as `ToastData` or a render function for custom layouts.
|
|
2447
|
+
* @param toastProps - Optional per-toast overrides: id, duration, position.
|
|
2448
|
+
*/
|
|
2388
2449
|
const toast$1 = useCallback((data, toastProps) => {
|
|
2389
2450
|
if (typeof data === 'function') {
|
|
2390
2451
|
return toast.custom(data, toastProps);
|
|
@@ -2551,11 +2612,14 @@ function DCreditCard({ brand = 'visa', name, number, holderText = 'Card Holder',
|
|
|
2551
2612
|
}
|
|
2552
2613
|
|
|
2553
2614
|
const getItemClass = (action) => {
|
|
2554
|
-
const base =
|
|
2555
|
-
|
|
2615
|
+
const base = classNames({
|
|
2616
|
+
'dropdown-item d-flex align-items-center': true,
|
|
2617
|
+
[`dropdown-item-${action.color}`]: !!action.color,
|
|
2618
|
+
disabled: action.disabled,
|
|
2619
|
+
});
|
|
2556
2620
|
return base;
|
|
2557
2621
|
};
|
|
2558
|
-
function DDropdown({ actions, dropdownToggle, className, }) {
|
|
2622
|
+
function DDropdown({ actions, dropdownToggle, className, classNameMenu, }) {
|
|
2559
2623
|
const [open, setOpen] = useState(false);
|
|
2560
2624
|
const dropdownRef = useRef(null);
|
|
2561
2625
|
const [position, setPosition] = useState('down'); // 🆕
|
|
@@ -2597,14 +2661,14 @@ function DDropdown({ actions, dropdownToggle, className, }) {
|
|
|
2597
2661
|
else {
|
|
2598
2662
|
ToggleElement = (jsx(DButtonIcon, { variant: "link", stopPropagationEnabled: false, "aria-label": "Toggle Dropdown", "aria-haspopup": "menu", "aria-expanded": open, onClick: () => setOpen(!open), icon: "MoreVertical" }));
|
|
2599
2663
|
}
|
|
2600
|
-
return (jsxs("div", { className: `dropdown
|
|
2664
|
+
return (jsxs("div", { className: classNames(`dropdown drop-${position}`, className), ref: dropdownRef, children: [ToggleElement, jsx("ul", { style: {
|
|
2601
2665
|
position: 'absolute',
|
|
2602
2666
|
top: position === 'up' ? 'auto' : '100%',
|
|
2603
2667
|
bottom: position === 'up' ? '100%' : 'auto',
|
|
2604
2668
|
left: position === 'start' ? 'auto' : 0,
|
|
2605
2669
|
right: position === 'start' ? '0' : 'auto',
|
|
2606
2670
|
transform: 'translateY(4px)',
|
|
2607
|
-
}, className:
|
|
2671
|
+
}, className: classNames('dropdown-menu p-2', { show: open }, classNameMenu), children: actions.map((action, index) => {
|
|
2608
2672
|
if (action.isDivider) {
|
|
2609
2673
|
return (jsx("hr", { className: "dropdown-divider" }, index));
|
|
2610
2674
|
}
|
|
@@ -2861,5 +2925,5 @@ function DDataStateWrapper({ isLoading, isError, data, onRetry, renderLoading, r
|
|
|
2861
2925
|
return jsx(Fragment, { children: children(data) });
|
|
2862
2926
|
}
|
|
2863
2927
|
|
|
2864
|
-
export { DAlert, DAvatar, DBadge, DBox, DBoxFile, DButton, DButtonIcon, DCard$1 as DCard, DCardBody, DCardFooter, DCardHeader, DCarousel$1 as DCarousel, DCarouselSlide, DChip, DCollapse, DContext, DContextProvider, DCreditCard, DCurrencyText, DDataStateWrapper, DDatePicker, DDropdown, DErrorBoundary, DIcon, DIconBase, ForwardedDInput as DInput, DInputCheck, ForwardedDInputCounter as DInputCounter, ForwardedDInputCurrency as DInputCurrency, ForwardedDInputMask as DInputMask, ForwardedDInputPassword as DInputPassword, ForwardedDInputPhone as DInputPhone, DInputPin, ForwardedDInputRange as DInputRange, DInputSelect, DInputSwitch, DLayout$1 as DLayout, DLayoutPane, DListGroup$1 as DListGroup, DListGroupItem, DModal$1 as DModal, DModalBody, DModalFooter, DModalHeader, DOffcanvas$1 as DOffcanvas, DOffcanvasBody, DOffcanvasFooter, DOffcanvasHeader, DOtp, DPaginator, DPasswordStrengthMeter, DPopover, DProgress, DSelect$1 as DSelect, DStepper, DStepper$2 as DStepperDesktop, DStepper$1 as DStepperMobile, DTabContent, DTabs$1 as DTabs, DTimeline, DToast$1 as DToast, DToastContainer, DTooltip, DVoucher, changeQueryString, checkMediaQuery, configureI8n as configureI18n, formatCurrency, getCssVariable, getQueryString, subscribeToMediaQuery, useDContext, useDPortalContext, useDToast, useDisableBodyScrollEffect, useDisableInputWheel, useFormatCurrency, useInputCurrency, useItemSelection, useMediaBreakpointUpLg, useMediaBreakpointUpMd, useMediaBreakpointUpSm, useMediaBreakpointUpXl, useMediaBreakpointUpXs, useMediaBreakpointUpXxl, useMediaQuery,
|
|
2928
|
+
export { DAlert, DAvatar, DBadge, DBox, DBoxFile, DButton, DButtonIcon, DCard$1 as DCard, DCardBody, DCardFooter, DCardHeader, DCarousel$1 as DCarousel, DCarouselSlide, DChip, DCollapse, DContext, DContextProvider, DCreditCard, DCurrencyText, DDataStateWrapper, DDatePicker, DDropdown, DErrorBoundary, DIcon, DIconBase, ForwardedDInput as DInput, DInputCheck, ForwardedDInputCounter as DInputCounter, ForwardedDInputCurrency as DInputCurrency, ForwardedDInputMask as DInputMask, ForwardedDInputPassword as DInputPassword, ForwardedDInputPhone as DInputPhone, DInputPin, ForwardedDInputRange as DInputRange, DInputSelect, DInputSwitch, DLayout$1 as DLayout, DLayoutPane, DListGroup$1 as DListGroup, DListGroupItem, DModal$1 as DModal, DModalBody, DModalFooter, DModalHeader, DOffcanvas$1 as DOffcanvas, DOffcanvasBody, DOffcanvasFooter, DOffcanvasHeader, DOtp, DPaginator, DPasswordStrengthMeter, DPopover, DProgress, DSelect$1 as DSelect, DStepper, DStepper$2 as DStepperDesktop, DStepper$1 as DStepperMobile, DTabContent, DTabs$1 as DTabs, DTimeline, DToast$1 as DToast, DToastContainer, DTooltip, DVoucher, changeQueryString, checkMediaQuery, configureI8n as configureI18n, formatCurrency, getCssVariable, getQueryString, subscribeToMediaQuery, useDContext, useDPortalContext, useDToast, useDisableBodyScrollEffect, useDisableInputWheel, useFormatCurrency, useInputCurrency, useItemSelection, useMediaBreakpointUpLg, useMediaBreakpointUpMd, useMediaBreakpointUpSm, useMediaBreakpointUpXl, useMediaBreakpointUpXs, useMediaBreakpointUpXxl, useMediaQuery, useProvidedRefOrCreate, useStackState, useTabContext, validatePhoneNumber };
|
|
2865
2929
|
//# sourceMappingURL=index.esm.js.map
|