@flamingo-stack/openframe-frontend-core 0.0.267 → 0.0.268-snapshot.20260615081103
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/{chunk-YV55JZAD.cjs → chunk-5P22US65.cjs} +25 -25
- package/dist/{chunk-YV55JZAD.cjs.map → chunk-5P22US65.cjs.map} +1 -1
- package/dist/{chunk-O6UA475M.cjs → chunk-6HOVFLRN.cjs} +845 -700
- package/dist/chunk-6HOVFLRN.cjs.map +1 -0
- package/dist/{chunk-TPZI7NBN.cjs → chunk-O3QFZPGQ.cjs} +11 -11
- package/dist/{chunk-TPZI7NBN.cjs.map → chunk-O3QFZPGQ.cjs.map} +1 -1
- package/dist/{chunk-XSK72QRR.js → chunk-O3WINEZN.js} +2 -2
- package/dist/{chunk-CI5XE4LB.cjs → chunk-PKUIGYQF.cjs} +30 -30
- package/dist/{chunk-CI5XE4LB.cjs.map → chunk-PKUIGYQF.cjs.map} +1 -1
- package/dist/{chunk-GJVSLS2R.js → chunk-QVQ4YA46.js} +2 -2
- package/dist/{chunk-J6O57C7S.js → chunk-Z4475TMT.js} +3140 -2995
- package/dist/chunk-Z4475TMT.js.map +1 -0
- package/dist/{chunk-Z6MKG53Z.js → chunk-ZXNJLY4E.js} +2 -2
- package/dist/components/chat/index.cjs +2 -2
- package/dist/components/chat/index.js +1 -1
- package/dist/components/contact/index.cjs +3 -3
- package/dist/components/contact/index.js +2 -2
- package/dist/components/features/index.cjs +2 -2
- package/dist/components/features/index.js +1 -1
- package/dist/components/index.cjs +61 -47
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.js +17 -3
- package/dist/components/index.js.map +1 -1
- package/dist/components/navigation/index.cjs +2 -2
- package/dist/components/navigation/index.js +1 -1
- package/dist/components/related-content/index.cjs +3 -3
- package/dist/components/related-content/index.js +2 -2
- package/dist/components/tickets/index.cjs +53 -53
- package/dist/components/tickets/index.js +3 -3
- package/dist/components/ui/index.cjs +16 -2
- package/dist/components/ui/index.cjs.map +1 -1
- package/dist/components/ui/index.d.ts +1 -0
- package/dist/components/ui/index.d.ts.map +1 -1
- package/dist/components/ui/index.js +15 -1
- package/dist/components/ui/no-data/index.d.ts +5 -0
- package/dist/components/ui/no-data/index.d.ts.map +1 -0
- package/dist/components/ui/no-data/no-data-actions.d.ts +34 -0
- package/dist/components/ui/no-data/no-data-actions.d.ts.map +1 -0
- package/dist/components/ui/no-data/no-data-message.d.ts +17 -0
- package/dist/components/ui/no-data/no-data-message.d.ts.map +1 -0
- package/dist/components/ui/no-data/no-data-styles.d.ts +8 -0
- package/dist/components/ui/no-data/no-data-styles.d.ts.map +1 -0
- package/dist/components/ui/no-data/no-data.d.ts +33 -0
- package/dist/components/ui/no-data/no-data.d.ts.map +1 -0
- package/dist/index.cjs +16 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +15 -1
- package/dist/types/platform.d.ts +2 -0
- package/dist/types/platform.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/ui/index.ts +1 -0
- package/src/components/ui/no-data/index.ts +4 -0
- package/src/components/ui/no-data/no-data-actions.tsx +102 -0
- package/src/components/ui/no-data/no-data-message.tsx +43 -0
- package/src/components/ui/no-data/no-data-styles.ts +36 -0
- package/src/components/ui/no-data/no-data.tsx +84 -0
- package/src/stories/EmptyState.stories.tsx +207 -0
- package/src/types/platform.ts +6 -0
- package/dist/chunk-J6O57C7S.js.map +0 -1
- package/dist/chunk-O6UA475M.cjs.map +0 -1
- /package/dist/{chunk-XSK72QRR.js.map → chunk-O3WINEZN.js.map} +0 -0
- /package/dist/{chunk-GJVSLS2R.js.map → chunk-QVQ4YA46.js.map} +0 -0
- /package/dist/{chunk-Z6MKG53Z.js.map → chunk-ZXNJLY4E.js.map} +0 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import React from "react"
|
|
2
|
+
|
|
3
|
+
import { cn } from "../../../utils/cn"
|
|
4
|
+
import { noDataIconClasses } from "./no-data-styles"
|
|
5
|
+
|
|
6
|
+
interface NoDataMessageProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "title"> {
|
|
7
|
+
/** Leading glyph, sized to 16px (mobile) / 24px (md+). Optional. */
|
|
8
|
+
icon?: React.ReactNode
|
|
9
|
+
/** Primary line (body size). */
|
|
10
|
+
title?: React.ReactNode
|
|
11
|
+
/** Secondary line (caption size). */
|
|
12
|
+
description?: React.ReactNode
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* A transparent, centered stack of an icon, a title and a description, in muted
|
|
17
|
+
* gray. Any piece is optional, so it also covers "icon + title", "title only",
|
|
18
|
+
* and similar reduced forms.
|
|
19
|
+
*/
|
|
20
|
+
const NoDataMessage = React.forwardRef<HTMLDivElement, NoDataMessageProps>(
|
|
21
|
+
function NoDataMessage({ icon, title, description, className, ...props }, ref) {
|
|
22
|
+
return (
|
|
23
|
+
<div
|
|
24
|
+
ref={ref}
|
|
25
|
+
className={cn(
|
|
26
|
+
"flex flex-col items-center gap-[var(--spacing-system-l)] text-center text-ods-text-secondary",
|
|
27
|
+
className,
|
|
28
|
+
)}
|
|
29
|
+
{...props}
|
|
30
|
+
>
|
|
31
|
+
{icon && <span className={noDataIconClasses}>{icon}</span>}
|
|
32
|
+
{(title || description) && (
|
|
33
|
+
<div className="flex flex-col">
|
|
34
|
+
{title && <p className="text-h4 break-words">{title}</p>}
|
|
35
|
+
{description && <p className="text-h6 break-words">{description}</p>}
|
|
36
|
+
</div>
|
|
37
|
+
)}
|
|
38
|
+
</div>
|
|
39
|
+
)
|
|
40
|
+
},
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
export { NoDataMessage, type NoDataMessageProps }
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// Shared style atoms for the NoData (empty-state) family. Mirrors the approach
|
|
2
|
+
// used by `button-styles.ts`: a single source of truth for the icon scale, the
|
|
3
|
+
// block-group surface and the interactive/disabled treatment, expressed as
|
|
4
|
+
// reusable class atoms so new looks can be added without touching the markup.
|
|
5
|
+
|
|
6
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
7
|
+
|
|
8
|
+
// Leading-icon glyph scale: 16px on mobile, 24px on md+. Color is intentionally
|
|
9
|
+
// omitted so the glyph inherits the current text color (and dims with it when
|
|
10
|
+
// the block is disabled).
|
|
11
|
+
export const noDataIconClasses =
|
|
12
|
+
"inline-flex shrink-0 items-center justify-center [&_svg]:h-4 [&_svg]:w-4 md:[&_svg]:h-6 md:[&_svg]:w-6"
|
|
13
|
+
|
|
14
|
+
// Surface for the action-block group container: a card-colored panel with a
|
|
15
|
+
// border and rounded corners. `overflow-hidden` keeps only the outer blocks
|
|
16
|
+
// round — inner blocks stay square.
|
|
17
|
+
export const noDataActionsVariants = cva("overflow-hidden rounded-md", {
|
|
18
|
+
variants: {
|
|
19
|
+
variant: {
|
|
20
|
+
outline: "bg-ods-card border border-ods-border",
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
defaultVariants: { variant: "outline" },
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
export type NoDataActionsVariant = NonNullable<
|
|
27
|
+
VariantProps<typeof noDataActionsVariants>["variant"]
|
|
28
|
+
>
|
|
29
|
+
|
|
30
|
+
// Interactive treatment for a clickable block: hover/active surface tints, a
|
|
31
|
+
// keyboard focus ring, and a disabled state that grays the text and stops
|
|
32
|
+
// pointer interaction — matching the disabled outline button.
|
|
33
|
+
export const noDataActionInteractiveClasses =
|
|
34
|
+
"cursor-pointer transition-colors hover:bg-ods-bg-hover active:bg-ods-bg-active " +
|
|
35
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ods-focus focus-visible:ring-inset " +
|
|
36
|
+
"disabled:cursor-default disabled:pointer-events-none disabled:text-ods-text-disabled"
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import React from "react"
|
|
2
|
+
|
|
3
|
+
import { cn } from "../../../utils/cn"
|
|
4
|
+
import { Button, type ButtonProps } from "../button"
|
|
5
|
+
import { NoDataMessage } from "./no-data-message"
|
|
6
|
+
import { NoDataActions, type NoDataActionProps } from "./no-data-actions"
|
|
7
|
+
|
|
8
|
+
interface NoDataProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "title"> {
|
|
9
|
+
// --- Message ---
|
|
10
|
+
/** Leading glyph, sized to 16px (mobile) / 24px (md+). */
|
|
11
|
+
icon?: React.ReactNode
|
|
12
|
+
/** Primary line. */
|
|
13
|
+
title?: React.ReactNode
|
|
14
|
+
/** Secondary line. */
|
|
15
|
+
description?: React.ReactNode
|
|
16
|
+
|
|
17
|
+
// --- Clickable blocks ---
|
|
18
|
+
/** Clickable blocks. Dynamic count. Hidden when empty/omitted. */
|
|
19
|
+
actions?: NoDataActionProps[]
|
|
20
|
+
|
|
21
|
+
// --- Footer button ---
|
|
22
|
+
/** Footer button label. When set (and `button` is not), renders the button. */
|
|
23
|
+
buttonLabel?: React.ReactNode
|
|
24
|
+
/** Leading icon for the footer button. */
|
|
25
|
+
buttonIcon?: React.ReactNode
|
|
26
|
+
/** Click handler for the footer button. */
|
|
27
|
+
onButtonClick?: ButtonProps["onClick"]
|
|
28
|
+
/** Extra props forwarded to the footer button (variant, href, loading, …). */
|
|
29
|
+
buttonProps?: Partial<ButtonProps>
|
|
30
|
+
/** Fully custom footer node; overrides the `buttonLabel`/`buttonIcon` path. */
|
|
31
|
+
button?: React.ReactNode
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* A centered empty-state panel: a muted icon/title/description message, an
|
|
36
|
+
* optional group of clickable blocks, and an optional footer button, stacked
|
|
37
|
+
* vertically with breakpoint-aware spacing. Each region renders only when its
|
|
38
|
+
* inputs are present, so the same component covers a bare message, a message
|
|
39
|
+
* with a button, the full layout, and everything in between.
|
|
40
|
+
*/
|
|
41
|
+
const NoData = React.forwardRef<HTMLDivElement, NoDataProps>(function NoData(
|
|
42
|
+
{
|
|
43
|
+
icon,
|
|
44
|
+
title,
|
|
45
|
+
description,
|
|
46
|
+
actions,
|
|
47
|
+
buttonLabel,
|
|
48
|
+
buttonIcon,
|
|
49
|
+
onButtonClick,
|
|
50
|
+
buttonProps,
|
|
51
|
+
button,
|
|
52
|
+
className,
|
|
53
|
+
...props
|
|
54
|
+
},
|
|
55
|
+
ref,
|
|
56
|
+
) {
|
|
57
|
+
const hasMessage = !!(icon || title || description)
|
|
58
|
+
const hasActions = !!actions?.length
|
|
59
|
+
|
|
60
|
+
const footerButton =
|
|
61
|
+
button ??
|
|
62
|
+
(buttonLabel != null ? (
|
|
63
|
+
<Button variant="outline" leftIcon={buttonIcon} onClick={onButtonClick} {...buttonProps}>
|
|
64
|
+
{buttonLabel}
|
|
65
|
+
</Button>
|
|
66
|
+
) : null)
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
<div
|
|
70
|
+
ref={ref}
|
|
71
|
+
className={cn(
|
|
72
|
+
"flex w-full flex-col items-center justify-center gap-[var(--spacing-system-l)] p-[var(--spacing-system-l)]",
|
|
73
|
+
className,
|
|
74
|
+
)}
|
|
75
|
+
{...props}
|
|
76
|
+
>
|
|
77
|
+
{hasMessage && <NoDataMessage icon={icon} title={title} description={description} />}
|
|
78
|
+
{hasActions && <NoDataActions actions={actions} />}
|
|
79
|
+
{footerButton}
|
|
80
|
+
</div>
|
|
81
|
+
)
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
export { NoData, type NoDataProps }
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/nextjs-vite';
|
|
2
|
+
import { Database, FileText, Inbox, Plus, Search, Settings, Sparkles, Upload, Zap } from 'lucide-react';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { Button } from '../components/ui/button';
|
|
5
|
+
import { NoData, NoDataAction, NoDataActions, NoDataMessage } from '../components/ui/no-data';
|
|
6
|
+
|
|
7
|
+
const meta = {
|
|
8
|
+
title: 'UI/EmptyState',
|
|
9
|
+
component: NoData,
|
|
10
|
+
argTypes: {
|
|
11
|
+
icon: { control: false },
|
|
12
|
+
actions: { control: false },
|
|
13
|
+
button: { control: false },
|
|
14
|
+
buttonIcon: { control: false },
|
|
15
|
+
onButtonClick: { control: false },
|
|
16
|
+
buttonProps: { control: false },
|
|
17
|
+
title: { control: 'text' },
|
|
18
|
+
description: { control: 'text' },
|
|
19
|
+
buttonLabel: { control: 'text' },
|
|
20
|
+
},
|
|
21
|
+
} satisfies Meta<typeof NoData>;
|
|
22
|
+
|
|
23
|
+
export default meta;
|
|
24
|
+
type Story = StoryObj<typeof meta>;
|
|
25
|
+
|
|
26
|
+
const noop = () => {};
|
|
27
|
+
|
|
28
|
+
const defaultActions = [
|
|
29
|
+
{ icon: <Zap />, label: 'Feature Description', onClick: noop },
|
|
30
|
+
{ icon: <Sparkles />, label: 'Feature Description', onClick: noop },
|
|
31
|
+
{ icon: <Database />, label: 'Feature Description', onClick: noop },
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
// === Full composition ===
|
|
35
|
+
|
|
36
|
+
export const Default: Story = {
|
|
37
|
+
args: {
|
|
38
|
+
icon: <Inbox />,
|
|
39
|
+
title: 'No data available',
|
|
40
|
+
description: 'Start by adding an item',
|
|
41
|
+
actions: defaultActions,
|
|
42
|
+
buttonLabel: 'Ask Mingo about Item',
|
|
43
|
+
buttonIcon: <Sparkles />,
|
|
44
|
+
onButtonClick: noop,
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
// === Reduced message ===
|
|
49
|
+
|
|
50
|
+
export const MessageTitleOnly: Story = {
|
|
51
|
+
args: {
|
|
52
|
+
icon: <Search />,
|
|
53
|
+
title: 'No results found',
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
// === Without one region ===
|
|
58
|
+
|
|
59
|
+
export const WithoutActions: Story = {
|
|
60
|
+
args: {
|
|
61
|
+
icon: <Inbox />,
|
|
62
|
+
title: 'No data available',
|
|
63
|
+
description: 'Start by adding an item',
|
|
64
|
+
buttonLabel: 'Add item',
|
|
65
|
+
buttonIcon: <Plus />,
|
|
66
|
+
onButtonClick: noop,
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export const WithoutButton: Story = {
|
|
71
|
+
args: {
|
|
72
|
+
icon: <Inbox />,
|
|
73
|
+
title: 'No data available',
|
|
74
|
+
description: 'Start by adding an item',
|
|
75
|
+
actions: defaultActions,
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// === Dynamic block count ===
|
|
80
|
+
|
|
81
|
+
export const TwoActions: Story = {
|
|
82
|
+
args: {
|
|
83
|
+
icon: <Database />,
|
|
84
|
+
title: 'No data available',
|
|
85
|
+
description: 'Start by adding an item',
|
|
86
|
+
actions: [
|
|
87
|
+
{ icon: <Zap />, label: 'Feature Description', onClick: noop },
|
|
88
|
+
{ icon: <Sparkles />, label: 'Feature Description', onClick: noop },
|
|
89
|
+
],
|
|
90
|
+
buttonLabel: 'Ask Mingo about Item',
|
|
91
|
+
buttonIcon: <Sparkles />,
|
|
92
|
+
onButtonClick: noop,
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
export const FourActions: Story = {
|
|
97
|
+
args: {
|
|
98
|
+
icon: <Database />,
|
|
99
|
+
title: 'No data available',
|
|
100
|
+
description: 'Start by adding an item',
|
|
101
|
+
actions: [
|
|
102
|
+
{ icon: <Zap />, label: 'Real-time sync', onClick: noop },
|
|
103
|
+
{ icon: <Sparkles />, label: 'Smart suggestions', onClick: noop },
|
|
104
|
+
{ icon: <Database />, label: 'Unlimited storage', onClick: noop },
|
|
105
|
+
{ icon: <FileText />, label: 'Export anywhere', onClick: noop },
|
|
106
|
+
],
|
|
107
|
+
buttonLabel: 'Ask Mingo about Item',
|
|
108
|
+
buttonIcon: <Sparkles />,
|
|
109
|
+
onButtonClick: noop,
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
// === Disabled blocks ===
|
|
114
|
+
|
|
115
|
+
export const DisabledActions: Story = {
|
|
116
|
+
args: {
|
|
117
|
+
icon: <Inbox />,
|
|
118
|
+
title: 'No data available',
|
|
119
|
+
description: 'Some actions are unavailable',
|
|
120
|
+
actions: [
|
|
121
|
+
{ icon: <Zap />, label: 'Available', onClick: noop },
|
|
122
|
+
{ icon: <Sparkles />, label: 'Disabled', onClick: noop, disabled: true },
|
|
123
|
+
{ icon: <Database />, label: 'Disabled', onClick: noop, disabled: true },
|
|
124
|
+
],
|
|
125
|
+
buttonLabel: 'Ask Mingo about Item',
|
|
126
|
+
buttonIcon: <Sparkles />,
|
|
127
|
+
onButtonClick: noop,
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
// === Footer button variations ===
|
|
132
|
+
|
|
133
|
+
export const ButtonAsLink: Story = {
|
|
134
|
+
args: {
|
|
135
|
+
icon: <Upload />,
|
|
136
|
+
title: 'No data available',
|
|
137
|
+
description: 'Import your first dataset',
|
|
138
|
+
buttonLabel: 'View docs',
|
|
139
|
+
buttonIcon: <FileText />,
|
|
140
|
+
buttonProps: { href: '/docs' },
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
export const CustomButton: Story = {
|
|
145
|
+
args: {
|
|
146
|
+
icon: <Settings />,
|
|
147
|
+
title: 'No data available',
|
|
148
|
+
description: 'Configure a source to get started',
|
|
149
|
+
// `button` is the escape hatch — pass any node.
|
|
150
|
+
button: (
|
|
151
|
+
<div className="flex gap-2">
|
|
152
|
+
<Button variant="outline" leftIcon={<Plus />}>Connect source</Button>
|
|
153
|
+
<Button variant="transparent" leftIcon={<FileText />}>View docs</Button>
|
|
154
|
+
</div>
|
|
155
|
+
),
|
|
156
|
+
},
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
// === Standalone parts ===
|
|
160
|
+
|
|
161
|
+
export const StandaloneActions: Story = {
|
|
162
|
+
args: { title: '' },
|
|
163
|
+
render: () => (
|
|
164
|
+
<NoDataActions>
|
|
165
|
+
<NoDataAction icon={<Zap />} label="Clickable block" onClick={noop} />
|
|
166
|
+
<NoDataAction icon={<Sparkles />} label="Clickable block" onClick={noop} />
|
|
167
|
+
<NoDataAction icon={<Database />} label="Disabled block" onClick={noop} disabled />
|
|
168
|
+
</NoDataActions>
|
|
169
|
+
),
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
export const StandaloneMessage: Story = {
|
|
173
|
+
args: { title: '' },
|
|
174
|
+
render: () => (
|
|
175
|
+
<NoDataMessage
|
|
176
|
+
icon={<Search />}
|
|
177
|
+
title="No results found"
|
|
178
|
+
description="Try adjusting your filters"
|
|
179
|
+
/>
|
|
180
|
+
),
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
// === Showcase ===
|
|
184
|
+
|
|
185
|
+
export const Showcase: Story = {
|
|
186
|
+
args: { title: '' },
|
|
187
|
+
render: () => (
|
|
188
|
+
<div className="flex flex-col items-stretch gap-12">
|
|
189
|
+
<NoData
|
|
190
|
+
icon={<Inbox />}
|
|
191
|
+
title="No data available"
|
|
192
|
+
description="Start by adding an item"
|
|
193
|
+
actions={defaultActions}
|
|
194
|
+
buttonLabel="Ask Mingo about Item"
|
|
195
|
+
buttonIcon={<Sparkles />}
|
|
196
|
+
onButtonClick={noop}
|
|
197
|
+
/>
|
|
198
|
+
<NoData icon={<Search />} title="No results found" description="Try a different search" />
|
|
199
|
+
<NoData
|
|
200
|
+
icon={<Database />}
|
|
201
|
+
title="No data available"
|
|
202
|
+
description="Start by adding an item"
|
|
203
|
+
actions={defaultActions}
|
|
204
|
+
/>
|
|
205
|
+
</div>
|
|
206
|
+
),
|
|
207
|
+
};
|
package/src/types/platform.ts
CHANGED
|
@@ -11,6 +11,12 @@ export interface PlatformRecord {
|
|
|
11
11
|
description?: string;
|
|
12
12
|
is_active: boolean;
|
|
13
13
|
is_internal: boolean; // Whether this is an internal admin platform vs public-facing
|
|
14
|
+
// Universal-viewer: when true, content DALs return ALL platforms' rows (applyFilter=false),
|
|
15
|
+
// decoupled from is_internal. Read by getPlatformContentScopeMode (hub lib/platform-utils.ts).
|
|
16
|
+
serves_all_content: boolean;
|
|
17
|
+
// When false, skip activity-tracking + HubSpot sync for this platform's principals
|
|
18
|
+
// (formerly keyed on is_internal). Read by platformTracksActivity (hub lib/platform-utils.ts).
|
|
19
|
+
tracks_activity: boolean;
|
|
14
20
|
// Chat (Ask AI) wiring — populated only for platforms that host a chat surface.
|
|
15
21
|
// `chat_source_id` is the doc-source binding (`chat_admin_personas.chat_source_id`).
|
|
16
22
|
// `chat_source_rag_tables_version` is the per-platform RAG-table override version
|