@flamingo-stack/openframe-frontend-core 0.0.712 → 0.0.713

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 (73) hide show
  1. package/dist/{chunk-G3OMVCID.js → chunk-3BB3IEJI.js} +1 -1
  2. package/dist/{chunk-CSCJU6YC.cjs → chunk-3QGUDPIH.cjs} +10 -10
  3. package/dist/{chunk-N67XG5GY.js → chunk-6F4QOCGB.js} +1 -1
  4. package/dist/{chunk-5Y72YQEK.js → chunk-6MNAIQNR.js} +3 -3
  5. package/dist/{chunk-7HNYYNKE.js → chunk-CGHOH3GN.js} +2 -2
  6. package/dist/{chunk-WWJG4GVG.cjs → chunk-F2EACDOR.cjs} +22 -22
  7. package/dist/{chunk-RBYVFPER.js → chunk-H4J72PRA.js} +1 -1
  8. package/dist/{chunk-BXSRTBLU.cjs → chunk-IJKMILMG.cjs} +2 -2
  9. package/dist/{chunk-3SEEGNRE.js → chunk-IU4IO3CG.js} +3 -3
  10. package/dist/{chunk-UT3ODMBU.cjs → chunk-J7YIQJPS.cjs} +2 -2
  11. package/dist/{chunk-7NSU5EQD.cjs → chunk-KGAFUXGZ.cjs} +11 -11
  12. package/dist/{chunk-JGCFRTND.cjs → chunk-KMB7JHGG.cjs} +4 -4
  13. package/dist/{chunk-EFNKS5W4.js → chunk-KPUHSVJU.js} +1 -1
  14. package/dist/{chunk-L6ZQGWCX.cjs → chunk-OQKRXLTZ.cjs} +191 -110
  15. package/dist/{chunk-OPYODNV2.js → chunk-P6QCJXLD.js} +1 -1
  16. package/dist/{chunk-Z5SWJW5Q.cjs → chunk-QQQ46DFT.cjs} +23 -23
  17. package/dist/{chunk-3UAJLO5U.cjs → chunk-QU4AHNRL.cjs} +3 -3
  18. package/dist/{chunk-4UYKNOZG.js → chunk-RBVUIOIM.js} +2 -2
  19. package/dist/{chunk-5SDELRH3.js → chunk-RRYNHAEL.js} +1 -1
  20. package/dist/{chunk-FCAVAEHF.js → chunk-STPC2AQU.js} +701 -620
  21. package/dist/{chunk-OBZJICEA.cjs → chunk-TC4W7QDC.cjs} +3 -3
  22. package/dist/{chunk-T3CLXR43.cjs → chunk-YIUSW4DB.cjs} +15 -15
  23. package/dist/{cloud-tenants-KZUZGD4A.cjs → cloud-tenants-HRJYNUJM.cjs} +2 -2
  24. package/dist/{cloud-tenants-OGLVVQ7X.js → cloud-tenants-SM7WLEGG.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 +49 -0
  36. package/dist/components/features/approval-level.d.ts.map +1 -0
  37. package/dist/components/features/index.cjs +10 -2
  38. package/dist/components/features/index.d.ts +1 -0
  39. package/dist/components/features/index.d.ts.map +1 -1
  40. package/dist/components/features/index.js +9 -1
  41. package/dist/components/features/policy-configuration-panel.d.ts.map +1 -1
  42. package/dist/components/help-center-pages/index.cjs +39 -39
  43. package/dist/components/help-center-pages/index.js +10 -10
  44. package/dist/components/index.cjs +26 -18
  45. package/dist/components/index.js +16 -8
  46. package/dist/components/meeting-scheduler/index.cjs +11 -11
  47. package/dist/components/meeting-scheduler/index.js +1 -1
  48. package/dist/components/navigation/index.cjs +3 -3
  49. package/dist/components/navigation/index.js +2 -2
  50. package/dist/components/onboarding-guides/index.cjs +4 -4
  51. package/dist/components/onboarding-guides/index.js +3 -3
  52. package/dist/components/product-demo/index.cjs +6 -6
  53. package/dist/components/product-demo/index.js +6 -6
  54. package/dist/components/tickets/index.cjs +5 -5
  55. package/dist/components/tickets/index.js +4 -4
  56. package/dist/components/ui/index.cjs +2 -2
  57. package/dist/components/ui/index.js +1 -1
  58. package/dist/{devices-YGYJIXQY.cjs → devices-6XKQTQM5.cjs} +3 -3
  59. package/dist/{devices-LBMG42K6.js → devices-LXSFGGEZ.js} +1 -1
  60. package/dist/index.cjs +11 -3
  61. package/dist/index.js +10 -2
  62. package/dist/{knowledge-KTCVJIWN.cjs → knowledge-7PDZLXPO.cjs} +2 -2
  63. package/dist/{knowledge-H5BIWJVI.js → knowledge-Q4SPFOTN.js} +1 -1
  64. package/dist/{logs-DB5Z7M5Q.js → logs-SZ4VB4FE.js} +1 -1
  65. package/dist/{logs-RVCC2UQW.cjs → logs-TO3NELGJ.cjs} +10 -10
  66. package/dist/{policies-HV4IQCBV.cjs → policies-533GQVFM.cjs} +6 -6
  67. package/dist/{policies-EWUULFBR.js → policies-LB7VW2UB.js} +1 -1
  68. package/dist/{software-update-D4OVSWSG.cjs → software-update-DT2XSG7M.cjs} +6 -6
  69. package/dist/{software-update-6PXKRKBT.js → software-update-ENZNVGKP.js} +1 -1
  70. package/package.json +1 -1
  71. package/src/components/features/approval-level.tsx +149 -0
  72. package/src/components/features/index.ts +1 -0
  73. package/src/components/features/policy-configuration-panel.tsx +3 -12
package/dist/index.js CHANGED
@@ -33,7 +33,7 @@ import {
33
33
  isMegaMenu,
34
34
  navLinkLabel,
35
35
  siteNavHasMobileMenus
36
- } from "./chunk-EFNKS5W4.js";
36
+ } from "./chunk-KPUHSVJU.js";
37
37
  import {
38
38
  MobileNavigationDropdown,
39
39
  MultiLevelNavigation,
@@ -49,6 +49,8 @@ import {
49
49
  AIRequiredBadge,
50
50
  AIStatusIndicator,
51
51
  AIWarningsSection,
52
+ APPROVAL_LEVELS,
53
+ APPROVAL_LEVEL_META,
52
54
  Accordion,
53
55
  AccordionContent,
54
56
  AccordionItem,
@@ -83,6 +85,8 @@ import {
83
85
  AppLayoutDrawerTrigger,
84
86
  AppStoreBadge,
85
87
  AppWindowFrame,
88
+ ApprovalLevelControl,
89
+ ApprovalLevelMark,
86
90
  ApprovalRequestNotificationTile,
87
91
  ArrayEntryManager,
88
92
  ArticleDetailLayout,
@@ -561,7 +565,7 @@ import {
561
565
  useTrackerClock,
562
566
  useWalkthroughVideo,
563
567
  usersCountLabel
564
- } from "./chunk-FCAVAEHF.js";
568
+ } from "./chunk-STPC2AQU.js";
565
569
  import {
566
570
  Board,
567
571
  BoardColumn,
@@ -2084,6 +2088,8 @@ export {
2084
2088
  ANNOUNCEMENT_CTA_DEFAULTS,
2085
2089
  ANTHROPIC_SUPPORTED_IMAGE_MIME,
2086
2090
  APPROVAL_BLOCK_VARIANT,
2091
+ APPROVAL_LEVELS,
2092
+ APPROVAL_LEVEL_META,
2087
2093
  APPROVAL_STATUS,
2088
2094
  ASK_AI_OPEN_EVENT,
2089
2095
  ASSISTANT_TYPE,
@@ -2139,6 +2145,8 @@ export {
2139
2145
  AppWindowFrame,
2140
2146
  AppleIcon,
2141
2147
  ApprovalBatchMessage,
2148
+ ApprovalLevelControl,
2149
+ ApprovalLevelMark,
2142
2150
  ApprovalRequestMessage,
2143
2151
  ApprovalRequestNotificationTile,
2144
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 _chunkL6ZQGWCXcjs = require('./chunk-L6ZQGWCX.cjs');
11
+ var _chunkOQKRXLTZcjs = require('./chunk-OQKRXLTZ.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
- _chunkL6ZQGWCXcjs.KnowledgeBaseArticleView,
99
+ _chunkOQKRXLTZcjs.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-FCAVAEHF.js";
11
+ } from "./chunk-STPC2AQU.js";
12
12
  import "./chunk-ILNN6QRW.js";
13
13
  import "./chunk-LQYXMEYF.js";
14
14
  import "./chunk-4JPLYOS6.js";
@@ -16,7 +16,7 @@ import {
16
16
  ToolBadge,
17
17
  logSeverityVariant,
18
18
  logSourceLabels
19
- } from "./chunk-FCAVAEHF.js";
19
+ } from "./chunk-STPC2AQU.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 _chunkL6ZQGWCXcjs = require('./chunk-L6ZQGWCX.cjs');
19
+ var _chunkOQKRXLTZcjs = require('./chunk-OQKRXLTZ.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: _chunkL6ZQGWCXcjs.logSeverityVariant.call(void 0, severity) },
80
+ status: { label: severity, variant: _chunkOQKRXLTZcjs.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, _chunkL6ZQGWCXcjs.LogCopyIconButton, {});
152
+ var copyAction = () => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkOQKRXLTZcjs.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
- _chunkL6ZQGWCXcjs.LogsPageView,
158
+ _chunkOQKRXLTZcjs.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
- _chunkL6ZQGWCXcjs.LogsTableView,
166
+ _chunkOQKRXLTZcjs.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, _chunkL6ZQGWCXcjs.AppLayoutDrawerContainerContext.Provider, { value: dock, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
181
- _chunkL6ZQGWCXcjs.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, _chunkOQKRXLTZcjs.AppLayoutDrawerContainerContext.Provider, { value: dock, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
181
+ _chunkOQKRXLTZcjs.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, _chunkL6ZQGWCXcjs.ToolBadge, { toolType: _chunkHETQETPVcjs.normalizeToolTypeWithFallback.call(void 0, selected.source.toolType) })
193
+ value: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkOQKRXLTZcjs.ToolBadge, { toolType: _chunkHETQETPVcjs.normalizeToolTypeWithFallback.call(void 0, selected.source.toolType) })
194
194
  },
195
- { label: "Device", value: _chunkL6ZQGWCXcjs.logSourceLabels.call(void 0, selected.device).deviceName }
195
+ { label: "Device", value: _chunkOQKRXLTZcjs.logSourceLabels.call(void 0, selected.device).deviceName }
196
196
  ],
197
197
  deviceCard: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
198
- _chunkL6ZQGWCXcjs.DeviceCard,
198
+ _chunkOQKRXLTZcjs.DeviceCard,
199
199
  {
200
200
  ...LOGS_FIXTURE_DEVICE,
201
201
  actions: {
@@ -10,7 +10,7 @@ var _chunkKHXZFLINcjs = require('./chunk-KHXZFLIN.cjs');
10
10
 
11
11
 
12
12
 
13
- var _chunkL6ZQGWCXcjs = require('./chunk-L6ZQGWCX.cjs');
13
+ var _chunkOQKRXLTZcjs = require('./chunk-OQKRXLTZ.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: _chunkL6ZQGWCXcjs.computePolicySummary.call(void 0, POLICIES),
85
+ summary: _chunkOQKRXLTZcjs.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: _chunkL6ZQGWCXcjs.getPolicyTableStatus.call(void 0, item),
92
+ status: _chunkOQKRXLTZcjs.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
- _chunkL6ZQGWCXcjs.PoliciesTable,
106
+ _chunkOQKRXLTZcjs.PoliciesTable,
107
107
  {
108
108
  rows: POLICIES_FIXTURE.rows,
109
109
  rowAsLink: true,
110
- rightSlot: compact ? void 0 : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkL6ZQGWCXcjs.DataTable.RowCount, {}),
110
+ rightSlot: compact ? void 0 : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkOQKRXLTZcjs.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, _chunkL6ZQGWCXcjs.PolicySummaryCards, { summary: POLICIES_FIXTURE.summary, now: POLICIES_FIXTURE.now }),
115
+ !compact && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkOQKRXLTZcjs.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-FCAVAEHF.js";
13
+ } from "./chunk-STPC2AQU.js";
14
14
  import "./chunk-ILNN6QRW.js";
15
15
  import "./chunk-LQYXMEYF.js";
16
16
  import "./chunk-4JPLYOS6.js";
@@ -16,7 +16,7 @@ var _chunkKHXZFLINcjs = require('./chunk-KHXZFLIN.cjs');
16
16
 
17
17
 
18
18
 
19
- var _chunkL6ZQGWCXcjs = require('./chunk-L6ZQGWCX.cjs');
19
+ var _chunkOQKRXLTZcjs = require('./chunk-OQKRXLTZ.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
- _chunkL6ZQGWCXcjs.Autocomplete,
117
+ _chunkOQKRXLTZcjs.Autocomplete,
118
118
  {
119
- label: _chunkL6ZQGWCXcjs.PACKAGE_SEARCH_LABEL,
119
+ label: _chunkOQKRXLTZcjs.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: _chunkL6ZQGWCXcjs.PACKAGE_SEARCH_PLACEHOLDER
124
+ placeholder: _chunkOQKRXLTZcjs.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
- _chunkL6ZQGWCXcjs.SoftwareActionForm,
138
+ _chunkOQKRXLTZcjs.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
- _chunkL6ZQGWCXcjs.DeviceSelector,
150
+ _chunkOQKRXLTZcjs.DeviceSelector,
151
151
  {
152
152
  devices: selected,
153
153
  loading: false,
@@ -16,7 +16,7 @@ import {
16
16
  PACKAGE_SEARCH_LABEL,
17
17
  PACKAGE_SEARCH_PLACEHOLDER,
18
18
  SoftwareActionForm
19
- } from "./chunk-FCAVAEHF.js";
19
+ } from "./chunk-STPC2AQU.js";
20
20
  import "./chunk-ILNN6QRW.js";
21
21
  import "./chunk-LQYXMEYF.js";
22
22
  import "./chunk-4JPLYOS6.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flamingo-stack/openframe-frontend-core",
3
- "version": "0.0.712",
3
+ "version": "0.0.713",
4
4
  "description": "Shared design system and components for all Flamingo platforms",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -0,0 +1,149 @@
1
+ 'use client';
2
+
3
+ import type { ComponentType } from 'react';
4
+ import type { ApprovalLevel } from '../../types/permissions';
5
+ import { cn } from '../../utils/cn';
6
+ import { HeadsetIcon } from '../icons-v2-generated/audio-and-visual/headset-icon';
7
+ import { BannedIcon } from '../icons-v2-generated/security/banned-icon';
8
+ import { CheckCircleIcon } from '../icons-v2-generated/signs-and-symbols/check-circle-icon';
9
+ import { UserIcon } from '../icons-v2-generated/users/user-icon';
10
+ import { ToggleGroup, ToggleGroupItem } from '../toggle-group';
11
+ import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../ui/tooltip';
12
+ import { TouchFriendlyTooltip } from '../ui/touch-friendly-tooltip';
13
+
14
+ /** The approval levels, in the order a choice reads: from "runs on its own" to "never runs". */
15
+ export const APPROVAL_LEVELS: readonly ApprovalLevel[] = ['ALLOW', 'ASK_USER', 'ASK_TECHNICIAN', 'DENY'];
16
+
17
+ export interface ApprovalLevelMeta {
18
+ /** The level's name, as every surface writes it. */
19
+ label: string;
20
+ /** What the level means, in one line: the tooltip of its icon. */
21
+ hint: string;
22
+ Icon: ComponentType<{ size?: number; className?: string }>;
23
+ /** The level's colour when it is the one in force (semantic status tokens). */
24
+ toneClassName: string;
25
+ }
26
+
27
+ /**
28
+ * THE look and wording of an approval level: its name, its one-line meaning,
29
+ * its icon and its colour. The guardrails panel's dropdown, the icon control
30
+ * below and any read-only mark read it, so a level is the same everywhere.
31
+ */
32
+ export const APPROVAL_LEVEL_META: Record<ApprovalLevel, ApprovalLevelMeta> = {
33
+ ALLOW: {
34
+ label: 'Allow',
35
+ hint: 'Runs on its own. You get a summary after.',
36
+ Icon: CheckCircleIcon,
37
+ toneClassName: 'text-ods-success',
38
+ },
39
+ ASK_USER: {
40
+ label: 'Ask User',
41
+ hint: 'Asks the person at the computer first.',
42
+ Icon: UserIcon,
43
+ toneClassName: 'text-ods-warning',
44
+ },
45
+ ASK_TECHNICIAN: {
46
+ label: 'Ask Technician',
47
+ hint: 'Asks a technician first. Nothing runs until they approve.',
48
+ Icon: HeadsetIcon,
49
+ toneClassName: 'text-ods-warning',
50
+ },
51
+ DENY: { label: 'Restrict', hint: 'Never runs.', Icon: BannedIcon, toneClassName: 'text-ods-error' },
52
+ };
53
+
54
+ const ICON_PX = 16;
55
+
56
+ export interface ApprovalLevelMarkProps {
57
+ level: ApprovalLevel;
58
+ /** Icon only: the name is the mark's accessible name and its tooltip. Default false (icon and name). */
59
+ iconOnly?: boolean;
60
+ className?: string;
61
+ }
62
+
63
+ /** One level, read-only: its icon in its colour, with its name beside it or as its tooltip. */
64
+ export function ApprovalLevelMark({ level, iconOnly = false, className }: ApprovalLevelMarkProps) {
65
+ const { label, hint, Icon, toneClassName } = APPROVAL_LEVEL_META[level];
66
+ const mark = (
67
+ <span className={cn('inline-flex items-center gap-[var(--spacing-system-xxs)] text-h6', toneClassName, className)}>
68
+ <Icon size={ICON_PX} className="shrink-0" aria-hidden />
69
+ {iconOnly ? <span className="sr-only">{label}</span> : label}
70
+ </span>
71
+ );
72
+ return iconOnly ? (
73
+ <TouchFriendlyTooltip content={`${label}: ${hint}`} side="top">
74
+ {mark}
75
+ </TouchFriendlyTooltip>
76
+ ) : (
77
+ mark
78
+ );
79
+ }
80
+
81
+ export interface ApprovalLevelControlProps {
82
+ value: ApprovalLevel;
83
+ onChange: (level: ApprovalLevel) => void;
84
+ /** The id of the element that names what is being decided (the rule's label). */
85
+ 'aria-labelledby'?: string;
86
+ /** The level in force, written beside the icons. Default true: a row reads without hovering, and on touch. */
87
+ showLabel?: boolean;
88
+ disabled?: boolean;
89
+ className?: string;
90
+ }
91
+
92
+ /**
93
+ * A choice of approval level as four icons, one per level, in a single-choice
94
+ * group (arrow keys move, like every toggle group). Each icon has the level's
95
+ * name as its accessible name and a tooltip with what the level means (hover
96
+ * or keyboard focus; a tap selects). The level in force wears its colour, and its name
97
+ * is written beside the group, so the choice never depends on a tooltip.
98
+ */
99
+ export function ApprovalLevelControl({
100
+ value,
101
+ onChange,
102
+ 'aria-labelledby': labelledBy,
103
+ showLabel = true,
104
+ disabled = false,
105
+ className,
106
+ }: ApprovalLevelControlProps) {
107
+ const current = APPROVAL_LEVEL_META[value];
108
+ return (
109
+ <div className={cn('flex shrink-0 items-center gap-[var(--spacing-system-sf)]', className)}>
110
+ {showLabel && <span className={cn('whitespace-nowrap text-h6', current.toneClassName)}>{current.label}</span>}
111
+ <TooltipProvider delayDuration={150}>
112
+ <ToggleGroup
113
+ type="single"
114
+ variant="outline"
115
+ size="sm"
116
+ value={value}
117
+ disabled={disabled}
118
+ // Clicking the level in force reports '' (deselect): a rule always has a level.
119
+ onValueChange={(next: string) => {
120
+ if (next && next !== value) onChange(next as ApprovalLevel);
121
+ }}
122
+ aria-labelledby={labelledBy}
123
+ >
124
+ {APPROVAL_LEVELS.map(level => {
125
+ const { label, hint, Icon, toneClassName } = APPROVAL_LEVEL_META[level];
126
+ return (
127
+ // A plain tooltip (hover and keyboard focus): a tap must SELECT the level, and on
128
+ // touch the name beside the group says what is in force.
129
+ <Tooltip key={level}>
130
+ <TooltipTrigger asChild>
131
+ <ToggleGroupItem
132
+ value={level}
133
+ aria-label={label}
134
+ className={cn('px-2', level === value && toneClassName)}
135
+ >
136
+ <Icon size={ICON_PX} aria-hidden />
137
+ </ToggleGroupItem>
138
+ </TooltipTrigger>
139
+ <TooltipContent side="top" className="max-w-xs">
140
+ <b>{label}</b>: {hint}
141
+ </TooltipContent>
142
+ </Tooltip>
143
+ );
144
+ })}
145
+ </ToggleGroup>
146
+ </TooltipProvider>
147
+ </div>
148
+ );
149
+ }
@@ -87,6 +87,7 @@ export * from './highlight-video-combined-section';
87
87
  export * from './view-toggle';
88
88
  // AI Enrich components
89
89
  export * from './ai-enrich';
90
+ export * from './approval-level';
90
91
  export * from './policy-configuration-panel';
91
92
  export * from './policies';
92
93
  export * from './cloud-tenants';
@@ -14,23 +14,14 @@ import { useCollapsible } from '../chat/hooks/use-collapsible';
14
14
  import { ToolIcon } from '../tool-icon';
15
15
  import { Button } from '../ui/button';
16
16
  import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '../ui/dropdown-menu';
17
+ import { APPROVAL_LEVEL_META, APPROVAL_LEVELS } from './approval-level';
17
18
 
18
- const approvalLevelLabels: Record<ApprovalLevel, string> = {
19
- ALLOW: 'Allow',
20
- ASK_USER: 'Ask User',
21
- ASK_TECHNICIAN: 'Ask Technician',
22
- DENY: 'Restrict',
23
- };
24
-
25
- const approvalLevelOptions = (Object.keys(approvalLevelLabels) as ApprovalLevel[]).map(value => ({
26
- value,
27
- label: approvalLevelLabels[value],
28
- }));
19
+ const approvalLevelOptions = APPROVAL_LEVELS.map(value => ({ value, label: APPROVAL_LEVEL_META[value].label }));
29
20
 
30
21
  const POLICY_LEVEL_WIDTH = 'w-[180px]';
31
22
  const CATEGORY_LEVEL_WIDTH = 'w-[256px]';
32
23
 
33
- const getApprovalLevelLabel = (level: ApprovalLevel): string => approvalLevelLabels[level] ?? level;
24
+ const getApprovalLevelLabel = (level: ApprovalLevel): string => APPROVAL_LEVEL_META[level]?.label ?? level;
34
25
 
35
26
  const ApprovalLevelDropdown: FC<{
36
27
  value: ApprovalLevel | undefined;