@flamingo-stack/openframe-frontend-core 0.0.715 → 0.0.716

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.
Files changed (86) hide show
  1. package/dist/{chunk-W4CS6UJS.cjs → chunk-2V7D5GJX.cjs} +3 -3
  2. package/dist/{chunk-AQI74KC7.js → chunk-3AJIQPFG.js} +3 -3
  3. package/dist/{chunk-EORJFB2Z.cjs → chunk-5IJXM3RU.cjs} +2 -2
  4. package/dist/{chunk-DI5VLY3G.js → chunk-64F6OEEV.js} +1 -1
  5. package/dist/{chunk-JHSPIDV5.js → chunk-BVZ7W4HW.js} +1 -1
  6. package/dist/{chunk-2LZ3IYGT.js → chunk-C5AGSZBT.js} +2268 -2209
  7. package/dist/{chunk-S66W6HNZ.cjs → chunk-DHMO5GI4.cjs} +10 -10
  8. package/dist/{chunk-WEEZSGFD.cjs → chunk-DLEO53NX.cjs} +23 -23
  9. package/dist/{chunk-4GFAKUHF.js → chunk-DPX6244M.js} +1 -1
  10. package/dist/{chunk-GXHWSAV6.cjs → chunk-I5F2OTFE.cjs} +15 -15
  11. package/dist/{chunk-VBDGMXZO.js → chunk-JCA5MBVY.js} +1 -1
  12. package/dist/{chunk-XFFIUXVI.cjs → chunk-KNOZVVCU.cjs} +2 -2
  13. package/dist/{chunk-OQVGA3YE.js → chunk-KYFNFRSV.js} +1 -1
  14. package/dist/{chunk-BIFUUH4K.js → chunk-MXPQMQI3.js} +3 -3
  15. package/dist/{chunk-U4WCFIYB.cjs → chunk-NKILEG3Y.cjs} +22 -22
  16. package/dist/{chunk-QW7KTWLB.js → chunk-P7IL4CX3.js} +2 -2
  17. package/dist/{chunk-ZSJ6WWFH.cjs → chunk-S2VWQX6T.cjs} +190 -131
  18. package/dist/{chunk-LTLHCAZY.cjs → chunk-STCJYO2Z.cjs} +4 -4
  19. package/dist/{chunk-KSEOIICU.js → chunk-V36WGIYR.js} +2 -2
  20. package/dist/{chunk-E25A235W.cjs → chunk-X2MNNV5H.cjs} +3 -3
  21. package/dist/{chunk-5MMCYJAJ.cjs → chunk-YO5JB3WE.cjs} +11 -11
  22. package/dist/{chunk-VKIRTB7K.js → chunk-YTMV4OBY.js} +1 -1
  23. package/dist/{cloud-tenants-MI7APZJD.cjs → cloud-tenants-2J7CPTKT.cjs} +2 -2
  24. package/dist/{cloud-tenants-NSEVWC26.js → cloud-tenants-YOY2WLGC.js} +1 -1
  25. package/dist/components/case-studies/index.cjs +10 -10
  26. package/dist/components/case-studies/index.js +2 -2
  27. package/dist/components/contact/index.cjs +3 -3
  28. package/dist/components/contact/index.js +2 -2
  29. package/dist/components/docs/index.cjs +5 -5
  30. package/dist/components/docs/index.js +4 -4
  31. package/dist/components/embeds/index.cjs +3 -3
  32. package/dist/components/embeds/index.js +2 -2
  33. package/dist/components/faq/index.cjs +3 -3
  34. package/dist/components/faq/index.js +2 -2
  35. package/dist/components/features/approval-level.d.ts +30 -22
  36. package/dist/components/features/approval-level.d.ts.map +1 -1
  37. package/dist/components/features/index.cjs +2 -4
  38. package/dist/components/features/index.js +3 -5
  39. package/dist/components/help-center-pages/index.cjs +39 -39
  40. package/dist/components/help-center-pages/index.js +10 -10
  41. package/dist/components/index.cjs +18 -18
  42. package/dist/components/index.js +12 -12
  43. package/dist/components/meeting-scheduler/index.cjs +11 -11
  44. package/dist/components/meeting-scheduler/index.js +1 -1
  45. package/dist/components/navigation/index.cjs +3 -3
  46. package/dist/components/navigation/index.js +2 -2
  47. package/dist/components/onboarding-guides/index.cjs +4 -4
  48. package/dist/components/onboarding-guides/index.js +3 -3
  49. package/dist/components/product-demo/index.cjs +6 -6
  50. package/dist/components/product-demo/index.js +6 -6
  51. package/dist/components/tickets/index.cjs +5 -5
  52. package/dist/components/tickets/index.js +4 -4
  53. package/dist/components/ui/analyzing-state.d.ts +17 -0
  54. package/dist/components/ui/analyzing-state.d.ts.map +1 -0
  55. package/dist/components/ui/feature-list.d.ts +4 -4
  56. package/dist/components/ui/feature-list.d.ts.map +1 -1
  57. package/dist/components/ui/incident-feed.d.ts +4 -1
  58. package/dist/components/ui/incident-feed.d.ts.map +1 -1
  59. package/dist/components/ui/index.cjs +4 -2
  60. package/dist/components/ui/index.d.ts +1 -0
  61. package/dist/components/ui/index.d.ts.map +1 -1
  62. package/dist/components/ui/index.js +3 -1
  63. package/dist/components/ui/playback-toggle.d.ts +10 -4
  64. package/dist/components/ui/playback-toggle.d.ts.map +1 -1
  65. package/dist/components/ui/tab-navigation.d.ts +7 -1
  66. package/dist/components/ui/tab-navigation.d.ts.map +1 -1
  67. package/dist/{devices-6NMK4EXV.cjs → devices-5NADSKDZ.cjs} +3 -3
  68. package/dist/{devices-W3VKQEVZ.js → devices-EQXXILXW.js} +1 -1
  69. package/dist/index.cjs +3 -3
  70. package/dist/index.js +6 -6
  71. package/dist/{knowledge-GDMGHFEC.cjs → knowledge-LHQYZJE7.cjs} +2 -2
  72. package/dist/{knowledge-YWCB7HNC.js → knowledge-YCQITBJB.js} +1 -1
  73. package/dist/{logs-7QDRV3GN.cjs → logs-DUVKSQU3.cjs} +10 -10
  74. package/dist/{logs-E742S5A2.js → logs-LZNXGOSW.js} +1 -1
  75. package/dist/{policies-BEVF6AEM.cjs → policies-5H74FS4S.cjs} +6 -6
  76. package/dist/{policies-XTPAKRHI.js → policies-VYWOJ7IF.js} +1 -1
  77. package/dist/{software-update-FXWIEKSW.js → software-update-MSDY3OLX.js} +1 -1
  78. package/dist/{software-update-KPHX4XQ7.cjs → software-update-VRRX5U4W.cjs} +6 -6
  79. package/package.json +1 -1
  80. package/src/components/features/approval-level.tsx +62 -44
  81. package/src/components/ui/analyzing-state.tsx +57 -0
  82. package/src/components/ui/feature-list.tsx +26 -16
  83. package/src/components/ui/incident-feed.tsx +6 -2
  84. package/src/components/ui/index.ts +1 -0
  85. package/src/components/ui/playback-toggle.tsx +12 -6
  86. package/src/components/ui/tab-navigation.tsx +12 -1
package/dist/index.js CHANGED
@@ -33,7 +33,7 @@ import {
33
33
  isMegaMenu,
34
34
  navLinkLabel,
35
35
  siteNavHasMobileMenus
36
- } from "./chunk-JHSPIDV5.js";
36
+ } from "./chunk-BVZ7W4HW.js";
37
37
  import {
38
38
  MobileNavigationDropdown,
39
39
  MultiLevelNavigation,
@@ -73,6 +73,7 @@ import {
73
73
  AlertDialogTrigger,
74
74
  AlertTitle,
75
75
  AllowedDomainsInput,
76
+ AnalyzingState,
76
77
  AnnouncementBarView,
77
78
  AppLayoutDrawerBody,
78
79
  AppLayoutDrawerClose,
@@ -85,8 +86,7 @@ import {
85
86
  AppLayoutDrawerTrigger,
86
87
  AppStoreBadge,
87
88
  AppWindowFrame,
88
- ApprovalLevelControl,
89
- ApprovalLevelMark,
89
+ ApprovalLevelView,
90
90
  ApprovalRequestNotificationTile,
91
91
  ArrayEntryManager,
92
92
  ArticleDetailLayout,
@@ -565,7 +565,7 @@ import {
565
565
  useTrackerClock,
566
566
  useWalkthroughVideo,
567
567
  usersCountLabel
568
- } from "./chunk-2LZ3IYGT.js";
568
+ } from "./chunk-C5AGSZBT.js";
569
569
  import {
570
570
  Board,
571
571
  BoardColumn,
@@ -2129,6 +2129,7 @@ export {
2129
2129
  AlertTitle,
2130
2130
  AlertTriangleIcon,
2131
2131
  AllowedDomainsInput,
2132
+ AnalyzingState,
2132
2133
  AnnouncementBarView,
2133
2134
  AppHeader,
2134
2135
  AppLayout,
@@ -2145,8 +2146,7 @@ export {
2145
2146
  AppWindowFrame,
2146
2147
  AppleIcon,
2147
2148
  ApprovalBatchMessage,
2148
- ApprovalLevelControl,
2149
- ApprovalLevelMark,
2149
+ ApprovalLevelView,
2150
2150
  ApprovalRequestMessage,
2151
2151
  ApprovalRequestNotificationTile,
2152
2152
  ApprovalStatusTag,
@@ -8,7 +8,7 @@ var _chunkII4QMH26cjs = require('./chunk-II4QMH26.cjs');
8
8
  var _chunkKHXZFLINcjs = require('./chunk-KHXZFLIN.cjs');
9
9
 
10
10
 
11
- var _chunkZSJ6WWFHcjs = require('./chunk-ZSJ6WWFH.cjs');
11
+ var _chunkS2VWQX6Tcjs = require('./chunk-S2VWQX6T.cjs');
12
12
  require('./chunk-4HJRHEXD.cjs');
13
13
  require('./chunk-HQQE74RO.cjs');
14
14
  require('./chunk-DEY6XXGO.cjs');
@@ -96,7 +96,7 @@ function KnowledgeScreen(_props) {
96
96
  const cast = _chunkII4QMH26cjs.useProductDemoCast.call(void 0, );
97
97
  const fixture = _react.useMemo.call(void 0, () => buildKnowledgeFixture(cast), [cast]);
98
98
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-full bg-ods-bg", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
99
- _chunkZSJ6WWFHcjs.KnowledgeBaseArticleView,
99
+ _chunkS2VWQX6Tcjs.KnowledgeBaseArticleView,
100
100
  {
101
101
  ...fixture.article,
102
102
  content: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkHETQETPVcjs.SimpleMarkdownRenderer, { content: fixture.content, textSize: "compact" })
@@ -8,7 +8,7 @@ import {
8
8
  } from "./chunk-CYUUHFXL.js";
9
9
  import {
10
10
  KnowledgeBaseArticleView
11
- } from "./chunk-2LZ3IYGT.js";
11
+ } from "./chunk-C5AGSZBT.js";
12
12
  import "./chunk-ILNN6QRW.js";
13
13
  import "./chunk-LQYXMEYF.js";
14
14
  import "./chunk-4JPLYOS6.js";
@@ -16,7 +16,7 @@ var _chunkKHXZFLINcjs = require('./chunk-KHXZFLIN.cjs');
16
16
 
17
17
 
18
18
 
19
- var _chunkZSJ6WWFHcjs = require('./chunk-ZSJ6WWFH.cjs');
19
+ var _chunkS2VWQX6Tcjs = require('./chunk-S2VWQX6T.cjs');
20
20
  require('./chunk-4HJRHEXD.cjs');
21
21
  require('./chunk-HQQE74RO.cjs');
22
22
  require('./chunk-DEY6XXGO.cjs');
@@ -77,7 +77,7 @@ function entry(logId, minutesAgo, severity, toolType, device2, summary) {
77
77
  id: logId,
78
78
  logId,
79
79
  timestamp: displayTime(_chunkKHXZFLINcjs.demoMinutesAgo.call(void 0, minutesAgo)),
80
- status: { label: severity, variant: _chunkZSJ6WWFHcjs.logSeverityVariant.call(void 0, severity) },
80
+ status: { label: severity, variant: _chunkS2VWQX6Tcjs.logSeverityVariant.call(void 0, severity) },
81
81
  source: { name: toolType, toolType },
82
82
  device: device2,
83
83
  description: { title: summary }
@@ -149,13 +149,13 @@ var NO_FILTERS = {};
149
149
  var ACTION_COLUMNS = ["copy", "quickView", "open"];
150
150
  var BESIDE_DRAWER_HIDDEN = [...ACTION_COLUMNS, "tool", "source"];
151
151
  var logHref = () => "#";
152
- var copyAction = () => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkZSJ6WWFHcjs.LogCopyIconButton, {});
152
+ var copyAction = () => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkS2VWQX6Tcjs.LogCopyIconButton, {});
153
153
  function LogsScreen({ compact = false }) {
154
154
  const [dock, setDock] = _react.useState.call(void 0, null);
155
155
  const selected = LOGS_FIXTURE_SELECTED;
156
156
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-full bg-ods-bg", children: [
157
157
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "min-w-0 flex-1 overflow-clip", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
158
- _chunkZSJ6WWFHcjs.LogsPageView,
158
+ _chunkS2VWQX6Tcjs.LogsPageView,
159
159
  {
160
160
  showHeader: false,
161
161
  className: "p-[var(--spacing-system-l)]",
@@ -163,7 +163,7 @@ function LogsScreen({ compact = false }) {
163
163
  onSearchChange: noop,
164
164
  onOpenFilters: noop,
165
165
  children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
166
- _chunkZSJ6WWFHcjs.LogsTableView,
166
+ _chunkS2VWQX6Tcjs.LogsTableView,
167
167
  {
168
168
  logs: LOGS_FIXTURE_ENTRIES,
169
169
  facets: LOGS_FIXTURE_FACETS,
@@ -177,8 +177,8 @@ function LogsScreen({ compact = false }) {
177
177
  )
178
178
  }
179
179
  ) }),
180
- !compact && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { ref: setDock, className: "relative w-[calc(400px+var(--spacing-system-m))] shrink-0", children: dock && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkZSJ6WWFHcjs.AppLayoutDrawerContainerContext.Provider, { value: dock, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
181
- _chunkZSJ6WWFHcjs.LogDrawer,
180
+ !compact && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { ref: setDock, className: "relative w-[calc(400px+var(--spacing-system-m))] shrink-0", children: dock && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkS2VWQX6Tcjs.AppLayoutDrawerContainerContext.Provider, { value: dock, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
181
+ _chunkS2VWQX6Tcjs.LogDrawer,
182
182
  {
183
183
  docked: true,
184
184
  isOpen: true,
@@ -190,12 +190,12 @@ function LogsScreen({ compact = false }) {
190
190
  { label: "Log ID", value: selected.logId },
191
191
  {
192
192
  label: "Source",
193
- value: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkZSJ6WWFHcjs.ToolBadge, { toolType: _chunkHETQETPVcjs.normalizeToolTypeWithFallback.call(void 0, selected.source.toolType) })
193
+ value: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkS2VWQX6Tcjs.ToolBadge, { toolType: _chunkHETQETPVcjs.normalizeToolTypeWithFallback.call(void 0, selected.source.toolType) })
194
194
  },
195
- { label: "Device", value: _chunkZSJ6WWFHcjs.logSourceLabels.call(void 0, selected.device).deviceName }
195
+ { label: "Device", value: _chunkS2VWQX6Tcjs.logSourceLabels.call(void 0, selected.device).deviceName }
196
196
  ],
197
197
  deviceCard: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
198
- _chunkZSJ6WWFHcjs.DeviceCard,
198
+ _chunkS2VWQX6Tcjs.DeviceCard,
199
199
  {
200
200
  ...LOGS_FIXTURE_DEVICE,
201
201
  actions: {
@@ -16,7 +16,7 @@ import {
16
16
  ToolBadge,
17
17
  logSeverityVariant,
18
18
  logSourceLabels
19
- } from "./chunk-2LZ3IYGT.js";
19
+ } from "./chunk-C5AGSZBT.js";
20
20
  import "./chunk-ILNN6QRW.js";
21
21
  import "./chunk-LQYXMEYF.js";
22
22
  import "./chunk-4JPLYOS6.js";
@@ -10,7 +10,7 @@ var _chunkKHXZFLINcjs = require('./chunk-KHXZFLIN.cjs');
10
10
 
11
11
 
12
12
 
13
- var _chunkZSJ6WWFHcjs = require('./chunk-ZSJ6WWFH.cjs');
13
+ var _chunkS2VWQX6Tcjs = require('./chunk-S2VWQX6T.cjs');
14
14
  require('./chunk-4HJRHEXD.cjs');
15
15
  require('./chunk-HQQE74RO.cjs');
16
16
  require('./chunk-DEY6XXGO.cjs');
@@ -82,14 +82,14 @@ var POLICIES = [
82
82
  policy("policy-local-admins", "No local admins", "No everyday account is a local administrator.", false, 0)
83
83
  ];
84
84
  var POLICIES_FIXTURE = {
85
- summary: _chunkZSJ6WWFHcjs.computePolicySummary.call(void 0, POLICIES),
85
+ summary: _chunkS2VWQX6Tcjs.computePolicySummary.call(void 0, POLICIES),
86
86
  rows: POLICIES.map((item) => ({
87
87
  id: item.id,
88
88
  name: item.name,
89
89
  description: item.description,
90
90
  critical: item.critical,
91
91
  severityLabel: item.critical ? "Critical" : "Low",
92
- status: _chunkZSJ6WWFHcjs.getPolicyTableStatus.call(void 0, item),
92
+ status: _chunkS2VWQX6Tcjs.getPolicyTableStatus.call(void 0, item),
93
93
  actions: [
94
94
  { label: "Policy Details", onClick: noop },
95
95
  { label: "Delete Policy", onClick: noop }
@@ -103,16 +103,16 @@ var POLICIES_FIXTURE = {
103
103
  var _jsxruntime = require('react/jsx-runtime');
104
104
  function PoliciesScreen({ compact = false }) {
105
105
  const table = /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
106
- _chunkZSJ6WWFHcjs.PoliciesTable,
106
+ _chunkS2VWQX6Tcjs.PoliciesTable,
107
107
  {
108
108
  rows: POLICIES_FIXTURE.rows,
109
109
  rowAsLink: true,
110
- rightSlot: compact ? void 0 : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkZSJ6WWFHcjs.DataTable.RowCount, {}),
110
+ rightSlot: compact ? void 0 : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkS2VWQX6Tcjs.DataTable.RowCount, {}),
111
111
  emptyMessage: "No policies found."
112
112
  }
113
113
  );
114
114
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-full flex-col gap-[var(--spacing-system-l)] bg-ods-bg p-[var(--spacing-system-l)]", children: [
115
- !compact && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkZSJ6WWFHcjs.PolicySummaryCards, { summary: POLICIES_FIXTURE.summary, now: POLICIES_FIXTURE.now }),
115
+ !compact && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkS2VWQX6Tcjs.PolicySummaryCards, { summary: POLICIES_FIXTURE.summary, now: POLICIES_FIXTURE.now }),
116
116
  table
117
117
  ] });
118
118
  }
@@ -10,7 +10,7 @@ import {
10
10
  PolicySummaryCards,
11
11
  computePolicySummary,
12
12
  getPolicyTableStatus
13
- } from "./chunk-2LZ3IYGT.js";
13
+ } from "./chunk-C5AGSZBT.js";
14
14
  import "./chunk-ILNN6QRW.js";
15
15
  import "./chunk-LQYXMEYF.js";
16
16
  import "./chunk-4JPLYOS6.js";
@@ -16,7 +16,7 @@ import {
16
16
  PACKAGE_SEARCH_LABEL,
17
17
  PACKAGE_SEARCH_PLACEHOLDER,
18
18
  SoftwareActionForm
19
- } from "./chunk-2LZ3IYGT.js";
19
+ } from "./chunk-C5AGSZBT.js";
20
20
  import "./chunk-ILNN6QRW.js";
21
21
  import "./chunk-LQYXMEYF.js";
22
22
  import "./chunk-4JPLYOS6.js";
@@ -16,7 +16,7 @@ var _chunkKHXZFLINcjs = require('./chunk-KHXZFLIN.cjs');
16
16
 
17
17
 
18
18
 
19
- var _chunkZSJ6WWFHcjs = require('./chunk-ZSJ6WWFH.cjs');
19
+ var _chunkS2VWQX6Tcjs = require('./chunk-S2VWQX6T.cjs');
20
20
  require('./chunk-4HJRHEXD.cjs');
21
21
  require('./chunk-HQQE74RO.cjs');
22
22
  require('./chunk-DEY6XXGO.cjs');
@@ -114,14 +114,14 @@ var noop = () => {
114
114
  var HIDDEN_WHEN_COMPACT = ["organization"];
115
115
  function StaticPackageField({ value }) {
116
116
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
117
- _chunkZSJ6WWFHcjs.Autocomplete,
117
+ _chunkS2VWQX6Tcjs.Autocomplete,
118
118
  {
119
- label: _chunkZSJ6WWFHcjs.PACKAGE_SEARCH_LABEL,
119
+ label: _chunkS2VWQX6Tcjs.PACKAGE_SEARCH_LABEL,
120
120
  labelVariant: "large",
121
121
  options: value ? [{ value: value.id, label: value.name, description: _nullishCoalesce(value.description, () => ( void 0)) }] : [],
122
122
  value: _nullishCoalesce(_optionalChain([value, 'optionalAccess', _ => _.id]), () => ( null)),
123
123
  onChange: noop,
124
- placeholder: _chunkZSJ6WWFHcjs.PACKAGE_SEARCH_PLACEHOLDER
124
+ placeholder: _chunkS2VWQX6Tcjs.PACKAGE_SEARCH_PLACEHOLDER
125
125
  }
126
126
  );
127
127
  }
@@ -135,7 +135,7 @@ function SoftwareUpdateScreen({ compact = false }) {
135
135
  [fixture.devices, fixture.selectedIds]
136
136
  );
137
137
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-full bg-ods-bg pt-[var(--spacing-system-l)]", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-full", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
138
- _chunkZSJ6WWFHcjs.SoftwareActionForm,
138
+ _chunkS2VWQX6Tcjs.SoftwareActionForm,
139
139
  {
140
140
  action: fixture.action,
141
141
  showHeader: false,
@@ -147,7 +147,7 @@ function SoftwareUpdateScreen({ compact = false }) {
147
147
  initialValues: fixture.initialValues,
148
148
  renderPackageSearch,
149
149
  renderDevicePicker: () => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
150
- _chunkZSJ6WWFHcjs.DeviceSelector,
150
+ _chunkS2VWQX6Tcjs.DeviceSelector,
151
151
  {
152
152
  devices: selected,
153
153
  loading: false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flamingo-stack/openframe-frontend-core",
3
- "version": "0.0.715",
3
+ "version": "0.0.716",
4
4
  "description": "Shared design system and components for all Flamingo platforms",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -30,8 +30,8 @@ export interface ApprovalLevelMeta {
30
30
 
31
31
  /**
32
32
  * THE look and wording of an approval level: its name, its one-line meaning,
33
- * its icon and its colour. The guardrails panel's dropdown, the icon control
34
- * below and any read-only mark read it, so a level is the same everywhere.
33
+ * its icon and its colour. The guardrails panel's dropdown and `ApprovalLevelView`
34
+ * below read it, so a level is the same everywhere.
35
35
  */
36
36
  export const APPROVAL_LEVEL_META: Record<ApprovalLevel, ApprovalLevelMeta> = {
37
37
  ALLOW: {
@@ -57,61 +57,79 @@ export const APPROVAL_LEVEL_META: Record<ApprovalLevel, ApprovalLevelMeta> = {
57
57
 
58
58
  const ICON_PX = 16;
59
59
 
60
- export interface ApprovalLevelMarkProps {
61
- level: ApprovalLevel;
62
- /** Icon only: the name is the mark's accessible name and its tooltip. Default false (icon and name). */
63
- iconOnly?: boolean;
64
- className?: string;
65
- }
66
-
67
- /** One level, read-only: its icon in its colour, with its name beside it or as its tooltip. */
68
- export function ApprovalLevelMark({ level, iconOnly = false, className }: ApprovalLevelMarkProps) {
69
- const { label, hint, Icon, toneClassName } = APPROVAL_LEVEL_META[level];
70
- const mark = (
71
- <span className={cn('inline-flex items-center gap-[var(--spacing-system-xxs)] text-h6', toneClassName, className)}>
72
- <Icon size={ICON_PX} className="shrink-0" aria-hidden />
73
- {iconOnly ? <span className="sr-only">{label}</span> : label}
74
- </span>
75
- );
76
- return iconOnly ? (
77
- <TouchFriendlyTooltip content={`${label}: ${hint}`} side="top">
78
- {mark}
79
- </TouchFriendlyTooltip>
80
- ) : (
81
- mark
82
- );
83
- }
84
-
85
- export interface ApprovalLevelControlProps {
60
+ export interface ApprovalLevelViewProps {
61
+ /** The level in force. */
86
62
  value: ApprovalLevel;
87
- onChange: (level: ApprovalLevel) => void;
88
- /** The id of the element that names what is being decided (the rule's label). */
89
- 'aria-labelledby'?: string;
90
- /** The level in force, written beside the icons. Default true: a row reads without hovering, and on touch. */
91
- showLabel?: boolean;
63
+ /**
64
+ * Whether the level can be changed here. `false`: the level's own icon.
65
+ * `true`: four icons, one per level, in a single-choice group. Default: true
66
+ * when `onChange` is given.
67
+ */
68
+ editable?: boolean;
69
+ /** Editable: the level picked. */
70
+ onChange?: (level: ApprovalLevel) => void;
71
+ /** Editable: the group is shown and cannot be changed (a locked rule). */
92
72
  disabled?: boolean;
73
+ /**
74
+ * The level's name, written before the icons. Default true: a row reads
75
+ * without hovering, and on touch. False keeps the name as the accessible
76
+ * name (and, read-only, as the icon's tooltip).
77
+ */
78
+ showLabel?: boolean;
79
+ /** Editable: the id of the element that names what is being decided (the rule's label). */
80
+ 'aria-labelledby'?: string;
93
81
  className?: string;
94
82
  }
95
83
 
96
84
  /**
97
- * A choice of approval level as four icons, one per level, in a single-choice
98
- * group (arrow keys move, like every toggle group). Each icon has the level's
99
- * name as its accessible name and a tooltip with what the level means (hover
100
- * or keyboard focus; a tap selects). The level in force wears its colour, and its name
101
- * is written beside the group, so the choice never depends on a tooltip.
85
+ * THE way a level is shown, read-only or editable, by one prop: the level's
86
+ * name in its colour, then its icon (read-only) or the four levels' icons as a
87
+ * single-choice group (editable; arrow keys move, like every toggle group).
88
+ * Name, icon, colour and tooltip are `APPROVAL_LEVEL_META`'s in both, so a
89
+ * rule reads the same on a page that shows it and on one that lets it change.
90
+ *
91
+ * Editable, each icon has its level's name as its accessible name and a
92
+ * tooltip with what the level means (hover or keyboard focus; a tap selects).
102
93
  */
103
- export function ApprovalLevelControl({
94
+ export function ApprovalLevelView({
104
95
  value,
96
+ editable,
105
97
  onChange,
106
- 'aria-labelledby': labelledBy,
107
- showLabel = true,
108
98
  disabled = false,
99
+ showLabel = true,
100
+ 'aria-labelledby': labelledBy,
109
101
  className,
110
- }: ApprovalLevelControlProps) {
102
+ }: ApprovalLevelViewProps) {
111
103
  const current = APPROVAL_LEVEL_META[value];
104
+ const canEdit = editable ?? onChange !== undefined;
105
+ const name = showLabel ? (
106
+ <span className={cn('whitespace-nowrap text-h6', current.toneClassName)}>{current.label}</span>
107
+ ) : null;
108
+
109
+ if (!canEdit) {
110
+ const icon = (
111
+ <span className={cn('inline-flex shrink-0', current.toneClassName)}>
112
+ <current.Icon size={ICON_PX} aria-hidden />
113
+ {!showLabel && <span className="sr-only">{current.label}</span>}
114
+ </span>
115
+ );
116
+ return (
117
+ <span className={cn('inline-flex shrink-0 items-center gap-[var(--spacing-system-xxs)]', className)}>
118
+ {name}
119
+ {showLabel ? (
120
+ icon
121
+ ) : (
122
+ <TouchFriendlyTooltip content={`${current.label}: ${current.hint}`} side="top">
123
+ {icon}
124
+ </TouchFriendlyTooltip>
125
+ )}
126
+ </span>
127
+ );
128
+ }
129
+
112
130
  return (
113
131
  <div className={cn('flex shrink-0 items-center gap-[var(--spacing-system-sf)]', className)}>
114
- {showLabel && <span className={cn('whitespace-nowrap text-h6', current.toneClassName)}>{current.label}</span>}
132
+ {name}
115
133
  <TooltipProvider delayDuration={150}>
116
134
  <ToggleGroup
117
135
  type="single"
@@ -121,7 +139,7 @@ export function ApprovalLevelControl({
121
139
  disabled={disabled}
122
140
  // Clicking the level in force reports '' (deselect): a rule always has a level.
123
141
  onValueChange={(next: string) => {
124
- if (next && next !== value) onChange(next as ApprovalLevel);
142
+ if (next && next !== value) onChange?.(next as ApprovalLevel);
125
143
  }}
126
144
  aria-labelledby={labelledBy}
127
145
  >
@@ -0,0 +1,57 @@
1
+ import { cn } from '../../utils/cn';
2
+ import { ChatTypingIndicator } from '../chat/chat-typing-indicator';
3
+ import { Skeleton } from './skeleton';
4
+
5
+ export interface AnalyzingStateProps {
6
+ /** What is being worked on, as a sentence with no closing mark ("Mingo is analyzing your logs"). */
7
+ label: string;
8
+ className?: string;
9
+ }
10
+
11
+ /** How far each row being read has faded: the list trails off instead of ending. */
12
+ const ROW_OPACITY = ['opacity-100', 'opacity-60', 'opacity-30'] as const;
13
+ /** Each row pulses a beat after the one above it, so the eye reads them as a scan. */
14
+ const ROW_STAGGER_MS = 200;
15
+
16
+ /**
17
+ * THE "it is working, nothing to show yet" state of a feed or a window: three
18
+ * rows still being read, pulsing one after another, over the caller's words
19
+ * and the chat's own typing dots. It says an agent is at work, where a bare
20
+ * sentence in an empty box reads as idle.
21
+ *
22
+ * Built from the shared pieces only: `Skeleton` for the rows and
23
+ * `ChatTypingIndicator` for the dots. Still under reduced motion. It is
24
+ * announced as a status; the rows and dots are decoration.
25
+ */
26
+ export function AnalyzingState({ label, className }: AnalyzingStateProps) {
27
+ return (
28
+ <div role="status" className={cn('flex w-full max-w-sm flex-col items-center gap-4', className)}>
29
+ <div aria-hidden className="grid w-full grid-cols-1 gap-2">
30
+ {ROW_OPACITY.map((opacity, row) => {
31
+ const delay = { animationDelay: `${row * ROW_STAGGER_MS}ms` };
32
+ return (
33
+ <div
34
+ key={opacity}
35
+ className={cn(
36
+ 'flex items-center gap-3 rounded-md border border-ods-border bg-ods-bg px-3.5 py-3',
37
+ opacity,
38
+ )}
39
+ >
40
+ <Skeleton
41
+ className="h-2 w-2 shrink-0 rounded-full bg-ods-flamingo-cyan motion-reduce:animate-none"
42
+ style={delay}
43
+ />
44
+ <Skeleton className="h-2.5 min-w-0 flex-1 motion-reduce:animate-none" style={delay} />
45
+ <Skeleton className="h-2.5 w-12 shrink-0 motion-reduce:animate-none" style={delay} />
46
+ </div>
47
+ );
48
+ })}
49
+ </div>
50
+ {/* A div, not a paragraph: the typing dots are block elements. */}
51
+ <div className="flex items-center gap-1.5 text-center text-ods-text-secondary text-h4">
52
+ {label}
53
+ <ChatTypingIndicator aria-hidden size="sm" dotClassName="bg-ods-text-secondary motion-reduce:animate-none" />
54
+ </div>
55
+ </div>
56
+ );
57
+ }
@@ -1,6 +1,7 @@
1
1
  'use client';
2
2
 
3
3
  import type React from 'react';
4
+ import { Button } from './button';
4
5
 
5
6
  export interface FeatureListItemData {
6
7
  /** Shown in the boxed slot. Not used by the `numbered` variant. */
@@ -15,13 +16,13 @@ export interface FeatureListProps {
15
16
  iconBoxSize?: number;
16
17
  /**
17
18
  * `boxed` (default): one bordered card, a boxed icon per row.
18
- * `numbered`: an ordered list of open rows separated by hairlines, each led
19
- * by its two-digit number (process steps).
19
+ * `numbered`: an ordered list of open rows, each led by its number in a
20
+ * round marker (process steps).
20
21
  */
21
22
  variant?: 'boxed' | 'numbered';
22
23
  /**
23
- * `numbered` only. The step being shown now: it stays at full strength and
24
- * the others step back, so the list reads as "you are here" beside a timed
24
+ * `numbered` only. The step being shown now: it stays at full strength with
25
+ * its marker lit and the others step back, so the list reads as "you are here" beside a timed
25
26
  * demo. Omit for a plain list where every step is equal.
26
27
  */
27
28
  activeIndex?: number;
@@ -43,38 +44,47 @@ export function FeatureList({
43
44
  if (variant === 'numbered') {
44
45
  const dims = typeof activeIndex === 'number';
45
46
  return (
46
- <ol className={`flex flex-col ${className}`}>
47
+ <ol className={`flex flex-col gap-[var(--spacing-system-lf)] ${className}`}>
47
48
  {items.map((item, index) => {
48
49
  const current = dims && index === activeIndex;
49
50
  const row = (
50
51
  <>
51
- <span className={`text-h5 ${current ? 'text-ods-flamingo-pink' : 'text-ods-text-secondary'}`}>
52
- {String(index + 1).padStart(2, '0')}
52
+ <span
53
+ className={`grid h-7 w-7 shrink-0 place-items-center rounded-full border transition-colors duration-200 text-h5 motion-reduce:transition-none ${
54
+ current
55
+ ? 'border-ods-flamingo-pink bg-ods-flamingo-pink-secondary text-ods-text-primary'
56
+ : 'border-ods-border text-ods-text-secondary'
57
+ }`}
58
+ >
59
+ {index + 1}
53
60
  </span>
54
61
  <div className="flex min-w-0 flex-col gap-[var(--spacing-system-xxs)]">
55
- <h3 className="text-ods-text-primary text-h3">{item.title}</h3>
56
- <p className="text-ods-text-secondary text-h4">{item.description}</p>
62
+ <h3 className="text-ods-text-primary text-h4">{item.title}</h3>
63
+ <p className="text-ods-text-secondary text-h6">{item.description}</p>
57
64
  </div>
58
65
  </>
59
66
  );
60
- const layout =
61
- 'grid grid-cols-[48px_minmax(0,1fr)] gap-[var(--spacing-system-m)] py-[var(--spacing-system-l)]';
67
+ const layout = 'flex items-start gap-[var(--spacing-system-sf)]';
62
68
  return (
63
69
  <li
64
70
  key={index}
65
71
  aria-current={current ? 'step' : undefined}
66
- className={`border-t border-ods-border transition-opacity duration-200 last:border-b motion-reduce:transition-none ${
72
+ className={`transition-opacity duration-200 motion-reduce:transition-none ${
67
73
  dims && !current ? 'opacity-55 focus-within:opacity-100 hover:opacity-100' : ''
68
74
  }`}
69
75
  >
70
76
  {onSelect ? (
71
- <button
72
- type="button"
77
+ // The unified Button with no box of its own (`wrap`): it brings the
78
+ // target, the focus ring and the keyboard semantics; the row is the look.
79
+ <Button
80
+ variant="transparent"
81
+ size="wrap"
82
+ fullWidth
73
83
  onClick={() => onSelect(index)}
74
- className={`${layout} w-full cursor-pointer text-left focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ods-focus`}
84
+ className={`${layout} justify-start whitespace-normal text-left hover:bg-transparent active:bg-transparent`}
75
85
  >
76
86
  {row}
77
- </button>
87
+ </Button>
78
88
  ) : (
79
89
  <div className={layout}>{row}</div>
80
90
  )}
@@ -1,5 +1,6 @@
1
1
  import type { ReactNode } from 'react';
2
2
  import { cn } from '../../utils/cn';
3
+ import { AnalyzingState } from './analyzing-state';
3
4
  import { StatusLine, type StatusLineTone } from './status-line';
4
5
 
5
6
  /** Where one incident stands. `waiting` is the only state that needs a person. */
@@ -46,7 +47,10 @@ export interface IncidentFeedProps {
46
47
  /** Oldest first. The newest is open; earlier ones collapse to a row. */
47
48
  items: readonly IncidentFeedItem[];
48
49
  statusLabels: Record<IncidentStatus, string>;
49
- /** Shown while there is nothing in the feed. */
50
+ /**
51
+ * Shown while there is nothing in the feed, under rows that are still being
52
+ * read: the agent is at work, it has just not found anything yet.
53
+ */
50
54
  emptyLabel?: string;
51
55
  /**
52
56
  * `top`: the list grows downward (a wide window). `bottom`: the newest item
@@ -91,7 +95,7 @@ export function IncidentFeed({ items, statusLabels, emptyLabel, anchor = 'top',
91
95
  className,
92
96
  )}
93
97
  >
94
- {items.length === 0 && emptyLabel && <p className="m-auto text-ods-text-secondary text-h4">{emptyLabel}</p>}
98
+ {items.length === 0 && emptyLabel && <AnalyzingState label={emptyLabel} className="m-auto" />}
95
99
  {items.map((item, index) => {
96
100
  const open = index === lastIndex || item.status === 'waiting';
97
101
  if (!open) {
@@ -236,6 +236,7 @@ export { LazyMount, type LazyMountProps } from './lazy-mount';
236
236
  export * from './app-window-frame';
237
237
  export * from './product-screen-frame';
238
238
  export * from './phone-frame';
239
+ export * from './analyzing-state';
239
240
  export * from './incident-feed';
240
241
  export * from './status-line';
241
242
  export * from './snap-carousel';
@@ -17,10 +17,16 @@ export interface PlaybackToggleProps {
17
17
 
18
18
  /**
19
19
  * THE stop/start control of anything that moves on its own (WCAG 2.2.2): one
20
- * small, quiet round icon button. A looping demo and an auto-advancing
21
- * carousel show the same one, wired to `useAutoplay`'s `paused` / `setPaused`.
22
- * Quiet on purpose: it takes the accent only on hover, so it never competes
23
- * with what it controls.
20
+ * small icon button beside what it controls. A looping demo and an
21
+ * auto-advancing carousel show the same one, wired to `useAutoplay`'s
22
+ * `paused` / `setPaused`.
23
+ *
24
+ * It has to be there and easy to reach (a 32px target, a name, a focus ring),
25
+ * never the thing the eye lands on: no border and no surface, only a small
26
+ * grey glyph that takes the accent on hover and focus. The grey is the muted
27
+ * text token, the quietest one that still clears the 3:1 a control's glyph
28
+ * needs against the page (WCAG 1.4.11); the next grey down does not. The
29
+ * target stays 32px; it is the glyph that is small.
24
30
  */
25
31
  export function PlaybackToggle({
26
32
  paused,
@@ -34,14 +40,14 @@ export function PlaybackToggle({
34
40
  variant="transparent"
35
41
  size="icon-sm"
36
42
  className={cn(
37
- 'shrink-0 rounded-full border border-ods-border text-ods-text-secondary hover:border-ods-accent hover:text-ods-accent',
43
+ 'shrink-0 rounded-full border-0 text-ods-text-muted hover:text-ods-accent focus-visible:text-ods-accent [&_svg]:h-3 [&_svg]:w-3',
38
44
  className,
39
45
  )}
40
46
  aria-label={paused ? playLabel : pauseLabel}
41
47
  aria-pressed={paused}
42
48
  onClick={() => onChange(!paused)}
43
49
  >
44
- {paused ? <PlayIcon size={16} /> : <PauseIcon size={16} />}
50
+ {paused ? <PlayIcon size={12} /> : <PauseIcon size={12} />}
45
51
  </Button>
46
52
  );
47
53
  }