@flamingo-stack/openframe-frontend-core 0.0.742 → 0.0.744
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/build/export-map.json +1 -1
- package/dist/{chunk-54EA4RLX.cjs → chunk-2JRCJV3M.cjs} +3 -3
- package/dist/{chunk-ZIFYSLIM.cjs → chunk-2UBR53AN.cjs} +4 -4
- package/dist/{chunk-Z2DQYKZA.cjs → chunk-35IQLGV3.cjs} +69 -69
- package/dist/{chunk-WIHHA54J.cjs → chunk-4A6OF4HI.cjs} +44 -44
- package/dist/{chunk-OBODY7F3.cjs → chunk-4N7KGOBS.cjs} +3 -3
- package/dist/{chunk-HIRVNBX5.cjs → chunk-65LJNDR2.cjs} +16 -16
- package/dist/{chunk-32Q7K5OP.cjs → chunk-7YDF3QBN.cjs} +116 -115
- package/dist/{chunk-DNFSMVXJ.cjs → chunk-AT6ZI4CO.cjs} +12 -12
- package/dist/{chunk-UWHCRIQQ.cjs → chunk-FTYQS6VI.cjs} +13 -13
- package/dist/{chunk-YQGDXH3M.cjs → chunk-GAGNKWOC.cjs} +2 -2
- package/dist/{chunk-L34TKFTS.cjs → chunk-H62FNZGG.cjs} +16 -16
- package/dist/{chunk-T433HSL6.cjs → chunk-HHL23RFC.cjs} +33 -33
- package/dist/{chunk-4PKORVOX.cjs → chunk-HJ4KGA2M.cjs} +441 -406
- package/dist/{chunk-4LDU32OB.cjs → chunk-HMSUYWSB.cjs} +4 -4
- package/dist/{chunk-UZLRSFGG.cjs → chunk-HTQJYN47.cjs} +30 -30
- package/dist/{chunk-XAA5EZ5T.cjs → chunk-JGZEHBBD.cjs} +6 -6
- package/dist/{chunk-5MH6BRPY.cjs → chunk-LJ46XYYP.cjs} +24 -12
- package/dist/{chunk-ISJXKKYW.cjs → chunk-NURAL5HD.cjs} +11 -11
- package/dist/{chunk-PS6T65KA.cjs → chunk-OC2LBQQJ.cjs} +90 -66
- package/dist/{chunk-HDBY2URA.cjs → chunk-PYWHDPVC.cjs} +31 -31
- package/dist/{chunk-R6SCSV2I.cjs → chunk-QSO56JZ2.cjs} +81 -81
- package/dist/{chunk-3LW43GIJ.cjs → chunk-QZYF2YQ3.cjs} +4 -4
- package/dist/{chunk-BI3XBCQX.cjs → chunk-YIOWV7LS.cjs} +2 -2
- package/dist/{chunk-H3UA7UY5.cjs → chunk-YJRMCFX3.cjs} +2 -2
- package/dist/{cloud-tenants-6ICAL3HO.cjs → cloud-tenants-JPXAXSPE.cjs} +7 -7
- package/dist/components/case-studies/index.cjs +19 -19
- package/dist/components/chat/entity-cards/onboarding-guide-card.d.ts.map +1 -1
- package/dist/components/chat/entity-cards/onboarding-guide-card.js +22 -12
- package/dist/components/chat/index.cjs +5 -5
- package/dist/components/chat/tool-execution-display.d.ts.map +1 -1
- package/dist/components/chat/tool-execution-display.js +5 -4
- package/dist/components/chat/utils/history-merge.d.ts.map +1 -1
- package/dist/components/chat/utils/history-merge.js +25 -1
- package/dist/components/contact/index.cjs +8 -8
- package/dist/components/docs/index.cjs +11 -11
- package/dist/components/embeds/index.cjs +8 -8
- package/dist/components/faq/index.cjs +9 -9
- package/dist/components/features/index.cjs +7 -7
- package/dist/components/features/scripts/schedule-form/schedule-interval-input.d.ts +1 -1
- package/dist/components/features/scripts/schedule-form/schedule-interval-input.d.ts.map +1 -1
- package/dist/components/features/scripts/schedule-form/schedule-interval-input.js +15 -13
- package/dist/components/features/scripts/schedule-form/schedule-offline-fields.d.ts.map +1 -1
- package/dist/components/features/scripts/schedule-form/schedule-offline-fields.js +9 -7
- package/dist/components/help-center-pages/index.cjs +101 -101
- package/dist/components/index.cjs +59 -57
- package/dist/components/meeting-scheduler/booking-form.d.ts +11 -1
- package/dist/components/meeting-scheduler/booking-form.d.ts.map +1 -1
- package/dist/components/meeting-scheduler/booking-form.js +15 -3
- package/dist/components/meeting-scheduler/index.cjs +408 -114
- package/dist/components/meeting-scheduler/index.d.ts +16 -1
- package/dist/components/meeting-scheduler/index.d.ts.map +1 -1
- package/dist/components/meeting-scheduler/index.js +157 -5
- package/dist/components/meeting-scheduler/modal-header.d.ts +27 -0
- package/dist/components/meeting-scheduler/modal-header.d.ts.map +1 -0
- package/dist/components/meeting-scheduler/modal-header.js +104 -0
- package/dist/components/meeting-scheduler/slot-picker.d.ts +13 -2
- package/dist/components/meeting-scheduler/slot-picker.d.ts.map +1 -1
- package/dist/components/meeting-scheduler/slot-picker.js +112 -73
- package/dist/components/navigation/index.cjs +10 -10
- package/dist/components/onboarding-guides/index.cjs +10 -10
- package/dist/components/product-demo/index.cjs +7 -7
- package/dist/components/related-content/index.cjs +5 -5
- package/dist/components/shared/product-release/product-release-card.d.ts.map +1 -1
- package/dist/components/shared/product-release/product-release-card.js +2 -0
- package/dist/components/tickets/index.cjs +13 -13
- package/dist/components/ui/index.cjs +9 -7
- package/dist/components/ui/radio-group.d.ts +6 -0
- package/dist/components/ui/radio-group.d.ts.map +1 -1
- package/dist/components/ui/radio-group.js +65 -58
- package/dist/components/ui/tab-navigation.d.ts +19 -1
- package/dist/components/ui/tab-navigation.d.ts.map +1 -1
- package/dist/components/ui/tab-navigation.js +32 -8
- package/dist/{devices-OFP2IBKN.cjs → devices-ONC4JOVH.cjs} +8 -8
- package/dist/{embeddable-chat-4C22MGNC.cjs → embeddable-chat-7ZEGCDVF.cjs} +71 -71
- package/dist/index.cjs +13 -11
- package/dist/{knowledge-KKBCSNUA.cjs → knowledge-G7XU5YST.cjs} +8 -8
- package/dist/{logs-X2GRNO57.cjs → logs-5B7NY4G6.cjs} +15 -15
- package/dist/{policies-35BXKB6P.cjs → policies-OYR3SLJN.cjs} +11 -11
- package/dist/{scripts-KQYVQOLU.cjs → scripts-6CWHTY6U.cjs} +12 -12
- package/dist/{software-update-ED33WSKT.cjs → software-update-AJPIY4SQ.cjs} +10 -10
- package/package.json +1 -1
- package/src/components/chat/entity-cards/onboarding-guide-card.tsx +8 -1
- package/src/components/chat/tool-execution-display.tsx +21 -10
- package/src/components/chat/utils/history-merge.ts +46 -1
- package/src/components/features/scripts/schedule-form/schedule-interval-input.tsx +20 -13
- package/src/components/features/scripts/schedule-form/schedule-offline-fields.tsx +9 -5
- package/src/components/meeting-scheduler/booking-form.tsx +29 -3
- package/src/components/meeting-scheduler/index.tsx +224 -3
- package/src/components/meeting-scheduler/modal-header.tsx +145 -0
- package/src/components/meeting-scheduler/slot-picker.tsx +72 -8
- package/src/components/shared/product-release/product-release-card.tsx +2 -0
- package/src/components/ui/radio-group.tsx +51 -36
- package/src/components/ui/tab-navigation.tsx +54 -5
|
@@ -47,6 +47,12 @@ interface RadioGroupBlockOption {
|
|
|
47
47
|
disabled?: boolean;
|
|
48
48
|
/** Optional trailing slot rendered at the end of the row (e.g. a discount tag) */
|
|
49
49
|
trailing?: ReactNode;
|
|
50
|
+
/**
|
|
51
|
+
* Optional content under the option's row, inside the option and across its
|
|
52
|
+
* full width (e.g. the fields the option needs on a narrow screen). Rendered
|
|
53
|
+
* as given, with no wrapper, so a footer hidden at some widths leaves no gap.
|
|
54
|
+
*/
|
|
55
|
+
footer?: ReactNode;
|
|
50
56
|
}
|
|
51
57
|
|
|
52
58
|
interface RadioGroupBlockProps extends Omit<ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root>, 'children'> {
|
|
@@ -99,42 +105,9 @@ const RadioGroupBlock = forwardRef<ComponentRef<typeof RadioGroupPrimitive.Root>
|
|
|
99
105
|
const itemId = `${props.name ?? 'radio-block'}-${option.value}`;
|
|
100
106
|
const isDisabled = disabled || option.disabled;
|
|
101
107
|
const isLast = index === options.length - 1;
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
htmlFor={itemId}
|
|
106
|
-
aria-disabled={isDisabled || undefined}
|
|
107
|
-
className={cn(
|
|
108
|
-
'flex w-full items-center gap-3',
|
|
109
|
-
isHorizontal && 'min-w-0 flex-1',
|
|
110
|
-
'transition-colors duration-200',
|
|
111
|
-
isDisabled ? 'cursor-not-allowed' : 'cursor-pointer',
|
|
112
|
-
// Hover / active move the BACKGROUND only, like Input and
|
|
113
|
-
// CheckboxBlock — the border stays put so an unselected row
|
|
114
|
-
// never flashes "selected" under the cursor.
|
|
115
|
-
!isDisabled && 'hover:bg-ods-bg-hover active:bg-ods-bg-active',
|
|
116
|
-
isGrouped
|
|
117
|
-
? cn(
|
|
118
|
-
'bg-ods-card px-[var(--spacing-system-sf)] py-[var(--spacing-system-xs,8px)]',
|
|
119
|
-
!isLast && (isHorizontal ? 'border-r' : 'border-b'),
|
|
120
|
-
error ? 'border-ods-error' : 'border-ods-border',
|
|
121
|
-
)
|
|
122
|
-
: cn(
|
|
123
|
-
'rounded-[6px] border bg-ods-card p-[var(--spacing-system-sf)]',
|
|
124
|
-
!isDisabled &&
|
|
125
|
-
'has-[[data-state=checked]]:bg-[var(--ods-system-greys-soft-grey)]/30 has-[[data-state=checked]]:border-ods-accent/40',
|
|
126
|
-
error ? 'border-ods-error' : 'border-ods-border',
|
|
127
|
-
),
|
|
128
|
-
// Disabled matches a disabled field: flat `ods-bg` fill and
|
|
129
|
-
// greyed text, not a fade of the whole row. The greying lives
|
|
130
|
-
// on the TEXT COLUMN below, not here: as a descendant rule on
|
|
131
|
-
// the row it also repainted whatever `trailing` renders — a
|
|
132
|
-
// `Tag`'s label is a span too, and it went invisible against
|
|
133
|
-
// its own fill.
|
|
134
|
-
isDisabled && 'bg-ods-bg',
|
|
135
|
-
itemClassName,
|
|
136
|
-
)}
|
|
137
|
-
>
|
|
108
|
+
const hasFooter = option.footer != null;
|
|
109
|
+
const row = (
|
|
110
|
+
<>
|
|
138
111
|
<RadioGroupPrimitive.Item
|
|
139
112
|
id={itemId}
|
|
140
113
|
value={option.value}
|
|
@@ -186,6 +159,48 @@ const RadioGroupBlock = forwardRef<ComponentRef<typeof RadioGroupPrimitive.Root>
|
|
|
186
159
|
)}
|
|
187
160
|
</div>
|
|
188
161
|
{option.trailing && <div className="ml-auto flex shrink-0 items-center">{option.trailing}</div>}
|
|
162
|
+
</>
|
|
163
|
+
);
|
|
164
|
+
return (
|
|
165
|
+
<label
|
|
166
|
+
key={option.value}
|
|
167
|
+
htmlFor={itemId}
|
|
168
|
+
aria-disabled={isDisabled || undefined}
|
|
169
|
+
className={cn(
|
|
170
|
+
'flex w-full items-center gap-3',
|
|
171
|
+
isHorizontal && 'min-w-0 flex-1',
|
|
172
|
+
'transition-colors duration-200',
|
|
173
|
+
isDisabled ? 'cursor-not-allowed' : 'cursor-pointer',
|
|
174
|
+
// Hover / active move the BACKGROUND only, like Input and
|
|
175
|
+
// CheckboxBlock — the border stays put so an unselected row
|
|
176
|
+
// never flashes "selected" under the cursor.
|
|
177
|
+
!isDisabled && 'hover:bg-ods-bg-hover active:bg-ods-bg-active',
|
|
178
|
+
isGrouped
|
|
179
|
+
? cn(
|
|
180
|
+
'bg-ods-card px-[var(--spacing-system-sf)] py-[var(--spacing-system-xs,8px)]',
|
|
181
|
+
!isLast && (isHorizontal ? 'border-r' : 'border-b'),
|
|
182
|
+
error ? 'border-ods-error' : 'border-ods-border',
|
|
183
|
+
)
|
|
184
|
+
: cn(
|
|
185
|
+
'rounded-[6px] border bg-ods-card p-[var(--spacing-system-sf)]',
|
|
186
|
+
!isDisabled &&
|
|
187
|
+
'has-[[data-state=checked]]:bg-[var(--ods-system-greys-soft-grey)]/30 has-[[data-state=checked]]:border-ods-accent/40',
|
|
188
|
+
error ? 'border-ods-error' : 'border-ods-border',
|
|
189
|
+
),
|
|
190
|
+
// Disabled matches a disabled field: flat `ods-bg` fill and
|
|
191
|
+
// greyed text, not a fade of the whole row. The greying lives
|
|
192
|
+
// on the TEXT COLUMN below, not here: as a descendant rule on
|
|
193
|
+
// the row it also repainted whatever `trailing` renders — a
|
|
194
|
+
// `Tag`'s label is a span too, and it went invisible against
|
|
195
|
+
// its own fill.
|
|
196
|
+
isDisabled && 'bg-ods-bg',
|
|
197
|
+
// With a footer the option stacks: its row, then the footer.
|
|
198
|
+
hasFooter && 'flex-col items-stretch gap-[var(--spacing-system-sf)]',
|
|
199
|
+
itemClassName,
|
|
200
|
+
)}
|
|
201
|
+
>
|
|
202
|
+
{hasFooter ? <div className="flex w-full items-center gap-[var(--spacing-system-sf)]">{row}</div> : row}
|
|
203
|
+
{option.footer}
|
|
189
204
|
</label>
|
|
190
205
|
);
|
|
191
206
|
})}
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
import type React from 'react';
|
|
4
4
|
import {
|
|
5
|
+
createContext,
|
|
6
|
+
useContext,
|
|
5
7
|
useState,
|
|
6
8
|
useEffect,
|
|
7
9
|
useLayoutEffect,
|
|
@@ -71,6 +73,31 @@ export interface TabItem {
|
|
|
71
73
|
accent?: string;
|
|
72
74
|
}
|
|
73
75
|
|
|
76
|
+
/**
|
|
77
|
+
* How a strip marks its tabs.
|
|
78
|
+
*
|
|
79
|
+
* - `default`: the tabs touch, and the open tab is marked by the underline alone.
|
|
80
|
+
* - `admin`: the product admin's tab bar. A gap between tabs, and the open and the
|
|
81
|
+
* hovered tab carry an accent fade above the underline.
|
|
82
|
+
*/
|
|
83
|
+
export type TabNavigationVariant = 'default' | 'admin';
|
|
84
|
+
|
|
85
|
+
const TabNavigationVariantContext = createContext<TabNavigationVariant>('default');
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Sets the variant of every `TabNavigation` below it that does not pass its own
|
|
89
|
+
* `variant`. An app whose tab bars all share one look mounts it once in its layout.
|
|
90
|
+
*/
|
|
91
|
+
export function TabNavigationVariantProvider({
|
|
92
|
+
variant,
|
|
93
|
+
children,
|
|
94
|
+
}: {
|
|
95
|
+
variant: TabNavigationVariant;
|
|
96
|
+
children: React.ReactNode;
|
|
97
|
+
}) {
|
|
98
|
+
return <TabNavigationVariantContext.Provider value={variant}>{children}</TabNavigationVariantContext.Provider>;
|
|
99
|
+
}
|
|
100
|
+
|
|
74
101
|
export interface TabNavigationUrlSyncOptions {
|
|
75
102
|
paramName?: string; // Default: 'tab'
|
|
76
103
|
replaceState?: boolean; // Default: true (use replace instead of push)
|
|
@@ -99,6 +126,8 @@ interface TabNavigationProps {
|
|
|
99
126
|
tabAlign?: 'center' | 'start';
|
|
100
127
|
/** How long the underline takes to reach a new `TabItem.progress` value. Default 200. */
|
|
101
128
|
progressTransitionMs?: number;
|
|
129
|
+
/** How the strip marks its tabs. Omitted: the nearest `TabNavigationVariantProvider`'s, else `default`. */
|
|
130
|
+
variant?: TabNavigationVariant;
|
|
102
131
|
|
|
103
132
|
// URL sync mode
|
|
104
133
|
urlSync?: boolean | TabNavigationUrlSyncOptions;
|
|
@@ -145,6 +174,7 @@ interface TabBarProps {
|
|
|
145
174
|
stretchTabs: boolean;
|
|
146
175
|
tabAlign: 'center' | 'start';
|
|
147
176
|
progressTransitionMs: number;
|
|
177
|
+
variant: TabNavigationVariant;
|
|
148
178
|
}
|
|
149
179
|
|
|
150
180
|
/**
|
|
@@ -170,7 +200,9 @@ const TabBar = memo(function TabBarImpl({
|
|
|
170
200
|
stretchTabs,
|
|
171
201
|
tabAlign,
|
|
172
202
|
progressTransitionMs,
|
|
203
|
+
variant,
|
|
173
204
|
}: TabBarProps) {
|
|
205
|
+
const isAdmin = variant === 'admin';
|
|
174
206
|
const scrollRef = useRef<HTMLDivElement>(null);
|
|
175
207
|
const activeTabRef = useRef<HTMLButtonElement>(null);
|
|
176
208
|
const isFirstActiveScrollRef = useRef(true);
|
|
@@ -396,7 +428,10 @@ const TabBar = memo(function TabBarImpl({
|
|
|
396
428
|
`relative` makes this the offsetParent the underline is measured against. */}
|
|
397
429
|
<div
|
|
398
430
|
ref={scrollRef}
|
|
399
|
-
className=
|
|
431
|
+
className={cn(
|
|
432
|
+
'scrollbar-hide relative flex h-full items-center justify-start overflow-x-auto overflow-y-hidden',
|
|
433
|
+
isAdmin && 'gap-[var(--spacing-system-xxs)]',
|
|
434
|
+
)}
|
|
400
435
|
>
|
|
401
436
|
{tabs.map(tab => {
|
|
402
437
|
const isActive = activeTab === tab.id;
|
|
@@ -417,11 +452,19 @@ const TabBar = memo(function TabBarImpl({
|
|
|
417
452
|
// `outline-none` above drops the browser's own focus ring, so
|
|
418
453
|
// put one back or the strip is un-navigable by keyboard — you
|
|
419
454
|
// can tab through it with nothing to show where you are. Inset,
|
|
420
|
-
// so it stays within the button
|
|
455
|
+
// so it stays within the button and never overlaps a neighbour.
|
|
421
456
|
'focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ods-focus',
|
|
422
457
|
stretchTabs && 'flex-1',
|
|
423
458
|
tab.avatar && 'gap-[var(--spacing-system-xsf)]',
|
|
424
|
-
//
|
|
459
|
+
// `default`: the open tab is marked by the underline alone, no surface
|
|
460
|
+
// of its own. `admin`: the open and the hovered tab carry an accent
|
|
461
|
+
// fade. ODS colour vars hold hex values, so Tailwind alpha modifiers
|
|
462
|
+
// (to-ods-accent/10) silently produce no CSS; color-mix() accepts
|
|
463
|
+
// hex, so the 10%-alpha stop is derived from the token.
|
|
464
|
+
isAdmin &&
|
|
465
|
+
(isActive
|
|
466
|
+
? 'bg-gradient-to-b from-transparent to-[color-mix(in_srgb,var(--color-accent-primary)_10%,transparent)]'
|
|
467
|
+
: 'hover:bg-gradient-to-b hover:from-transparent hover:to-[color-mix(in_srgb,var(--color-accent-primary)_10%,transparent)]'),
|
|
425
468
|
)}
|
|
426
469
|
>
|
|
427
470
|
{tab.avatar ? (
|
|
@@ -436,7 +479,7 @@ const TabBar = memo(function TabBarImpl({
|
|
|
436
479
|
'h-4 w-4 transition-colors content-md:h-6 content-md:w-6',
|
|
437
480
|
isActive
|
|
438
481
|
? !tab.accent && 'text-ods-accent'
|
|
439
|
-
: 'text-ods-text-secondary group-hover:text-ods-text-primary',
|
|
482
|
+
: cn('text-ods-text-secondary', !isAdmin && 'group-hover:text-ods-text-primary'),
|
|
440
483
|
)}
|
|
441
484
|
style={isActive && tab.accent ? { color: tab.accent } : undefined}
|
|
442
485
|
/>
|
|
@@ -453,7 +496,9 @@ const TabBar = memo(function TabBarImpl({
|
|
|
453
496
|
<span
|
|
454
497
|
className={cn(
|
|
455
498
|
'whitespace-nowrap transition-colors text-h4',
|
|
456
|
-
isActive
|
|
499
|
+
isActive
|
|
500
|
+
? 'text-ods-text-primary'
|
|
501
|
+
: cn('text-ods-text-secondary', !isAdmin && 'group-hover:text-ods-text-primary'),
|
|
457
502
|
)}
|
|
458
503
|
>
|
|
459
504
|
{tab.label}
|
|
@@ -542,10 +587,13 @@ export function TabNavigation({
|
|
|
542
587
|
stretchTabs = false,
|
|
543
588
|
tabAlign = 'center',
|
|
544
589
|
progressTransitionMs = 200,
|
|
590
|
+
variant: variantProp,
|
|
545
591
|
urlSync = false,
|
|
546
592
|
defaultTab,
|
|
547
593
|
children,
|
|
548
594
|
}: TabNavigationProps) {
|
|
595
|
+
const providedVariant = useContext(TabNavigationVariantContext);
|
|
596
|
+
const variant = variantProp ?? providedVariant;
|
|
549
597
|
const router = useRouter();
|
|
550
598
|
const pathname = usePathname();
|
|
551
599
|
const searchParams = useSearchParams();
|
|
@@ -717,6 +765,7 @@ export function TabNavigation({
|
|
|
717
765
|
stretchTabs={stretchTabs}
|
|
718
766
|
tabAlign={tabAlign}
|
|
719
767
|
progressTransitionMs={progressTransitionMs}
|
|
768
|
+
variant={variant}
|
|
720
769
|
/>
|
|
721
770
|
|
|
722
771
|
{/* Render children with active tab if provided */}
|