@almadar/ui 4.3.0 → 4.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -46317,18 +46317,24 @@ function renderContainedPortal(slot, content, onDismiss) {
46317
46317
  style: { minWidth: "520px", maxWidth: "700px", maxHeight: "80%" },
46318
46318
  onClick: (e) => e.stopPropagation(),
46319
46319
  children: [
46320
- content.props.title ? /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex items-center justify-between p-4 border-b border-border", children: [
46321
- /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h3", className: "text-lg font-semibold", children: String(content.props.title) }),
46320
+ /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: cn(
46321
+ "flex items-center p-4",
46322
+ content.props.title ? "justify-between border-b border-border" : "justify-end"
46323
+ ), children: [
46324
+ content.props.title ? /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h3", className: "text-lg font-semibold", children: String(content.props.title) }) : null,
46322
46325
  /* @__PURE__ */ jsxRuntime.jsx(
46323
46326
  Box,
46324
46327
  {
46325
46328
  as: "button",
46326
46329
  className: "text-muted-foreground hover:text-foreground cursor-pointer",
46327
46330
  onClick: onDismiss,
46331
+ "data-event": "CLOSE",
46332
+ "data-testid": "action-CLOSE",
46333
+ "aria-label": "Close modal",
46328
46334
  children: "\u2715"
46329
46335
  }
46330
46336
  )
46331
- ] }) : null,
46337
+ ] }),
46332
46338
  /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex-1 overflow-auto p-4", children: slotContent })
46333
46339
  ]
46334
46340
  }
@@ -46353,18 +46359,24 @@ function renderContainedPortal(slot, content, onDismiss) {
46353
46359
  ),
46354
46360
  onClick: (e) => e.stopPropagation(),
46355
46361
  children: [
46356
- content.props.title ? /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex items-center justify-between p-4 border-b border-border", children: [
46357
- /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h3", className: "text-lg font-semibold", children: String(content.props.title) }),
46362
+ /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: cn(
46363
+ "flex items-center p-4",
46364
+ content.props.title ? "justify-between border-b border-border" : "justify-end"
46365
+ ), children: [
46366
+ content.props.title ? /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h3", className: "text-lg font-semibold", children: String(content.props.title) }) : null,
46358
46367
  /* @__PURE__ */ jsxRuntime.jsx(
46359
46368
  Box,
46360
46369
  {
46361
46370
  as: "button",
46362
46371
  className: "text-muted-foreground hover:text-foreground cursor-pointer",
46363
46372
  onClick: onDismiss,
46373
+ "data-event": "CLOSE",
46374
+ "data-testid": "action-CLOSE",
46375
+ "aria-label": "Close drawer",
46364
46376
  children: "\u2715"
46365
46377
  }
46366
46378
  )
46367
- ] }) : null,
46379
+ ] }),
46368
46380
  /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "p-4", children: slotContent })
46369
46381
  ]
46370
46382
  }
@@ -46408,6 +46420,7 @@ function UISlotComponent({
46408
46420
  sourceTrait
46409
46421
  }) {
46410
46422
  const { slots, clear } = useUISlots();
46423
+ const eventBus = useEventBus();
46411
46424
  const suspenseConfig = React126.useContext(SuspenseConfigContext);
46412
46425
  const contained = React126.useContext(SlotContainedContext);
46413
46426
  const content = slots[slot];
@@ -46454,6 +46467,10 @@ function UISlotComponent({
46454
46467
  return null;
46455
46468
  }
46456
46469
  const handleDismiss = () => {
46470
+ if (slot === "modal" || slot === "drawer") {
46471
+ eventBus.emit("UI:CLOSE");
46472
+ eventBus.emit("UI:CANCEL");
46473
+ }
46457
46474
  clear(slot);
46458
46475
  };
46459
46476
  if (portal) {
@@ -46503,7 +46520,8 @@ function getOrCreatePortalRoot() {
46503
46520
  }
46504
46521
  function CompiledPortal({ slot, className, pattern, sourceTrait, children }) {
46505
46522
  const [portalRoot, setPortalRoot] = React126.useState(null);
46506
- const eventBus = useUISlots();
46523
+ const slotsBus = useUISlots();
46524
+ const eventBus = useEventBus();
46507
46525
  React126.useEffect(() => {
46508
46526
  setPortalRoot(getOrCreatePortalRoot());
46509
46527
  }, []);
@@ -46511,7 +46529,11 @@ function CompiledPortal({ slot, className, pattern, sourceTrait, children }) {
46511
46529
  if (portalRoot) getOrCreatePortalRoot();
46512
46530
  });
46513
46531
  const handleDismiss = () => {
46514
- eventBus.clear(slot);
46532
+ if (slot === "modal" || slot === "drawer") {
46533
+ eventBus.emit("UI:CLOSE");
46534
+ eventBus.emit("UI:CANCEL");
46535
+ }
46536
+ slotsBus.clear(slot);
46515
46537
  };
46516
46538
  if (!portalRoot) return null;
46517
46539
  const slotId = `slot-${slot}`;
@@ -46859,6 +46881,7 @@ var init_UISlotRenderer = __esm({
46859
46881
  init_Toast();
46860
46882
  init_Box();
46861
46883
  init_Typography();
46884
+ init_useEventBus();
46862
46885
  init_cn();
46863
46886
  init_ErrorBoundary();
46864
46887
  init_Skeleton();
package/dist/avl/index.js CHANGED
@@ -46271,18 +46271,24 @@ function renderContainedPortal(slot, content, onDismiss) {
46271
46271
  style: { minWidth: "520px", maxWidth: "700px", maxHeight: "80%" },
46272
46272
  onClick: (e) => e.stopPropagation(),
46273
46273
  children: [
46274
- content.props.title ? /* @__PURE__ */ jsxs(Box, { className: "flex items-center justify-between p-4 border-b border-border", children: [
46275
- /* @__PURE__ */ jsx(Typography, { variant: "h3", className: "text-lg font-semibold", children: String(content.props.title) }),
46274
+ /* @__PURE__ */ jsxs(Box, { className: cn(
46275
+ "flex items-center p-4",
46276
+ content.props.title ? "justify-between border-b border-border" : "justify-end"
46277
+ ), children: [
46278
+ content.props.title ? /* @__PURE__ */ jsx(Typography, { variant: "h3", className: "text-lg font-semibold", children: String(content.props.title) }) : null,
46276
46279
  /* @__PURE__ */ jsx(
46277
46280
  Box,
46278
46281
  {
46279
46282
  as: "button",
46280
46283
  className: "text-muted-foreground hover:text-foreground cursor-pointer",
46281
46284
  onClick: onDismiss,
46285
+ "data-event": "CLOSE",
46286
+ "data-testid": "action-CLOSE",
46287
+ "aria-label": "Close modal",
46282
46288
  children: "\u2715"
46283
46289
  }
46284
46290
  )
46285
- ] }) : null,
46291
+ ] }),
46286
46292
  /* @__PURE__ */ jsx(Box, { className: "flex-1 overflow-auto p-4", children: slotContent })
46287
46293
  ]
46288
46294
  }
@@ -46307,18 +46313,24 @@ function renderContainedPortal(slot, content, onDismiss) {
46307
46313
  ),
46308
46314
  onClick: (e) => e.stopPropagation(),
46309
46315
  children: [
46310
- content.props.title ? /* @__PURE__ */ jsxs(Box, { className: "flex items-center justify-between p-4 border-b border-border", children: [
46311
- /* @__PURE__ */ jsx(Typography, { variant: "h3", className: "text-lg font-semibold", children: String(content.props.title) }),
46316
+ /* @__PURE__ */ jsxs(Box, { className: cn(
46317
+ "flex items-center p-4",
46318
+ content.props.title ? "justify-between border-b border-border" : "justify-end"
46319
+ ), children: [
46320
+ content.props.title ? /* @__PURE__ */ jsx(Typography, { variant: "h3", className: "text-lg font-semibold", children: String(content.props.title) }) : null,
46312
46321
  /* @__PURE__ */ jsx(
46313
46322
  Box,
46314
46323
  {
46315
46324
  as: "button",
46316
46325
  className: "text-muted-foreground hover:text-foreground cursor-pointer",
46317
46326
  onClick: onDismiss,
46327
+ "data-event": "CLOSE",
46328
+ "data-testid": "action-CLOSE",
46329
+ "aria-label": "Close drawer",
46318
46330
  children: "\u2715"
46319
46331
  }
46320
46332
  )
46321
- ] }) : null,
46333
+ ] }),
46322
46334
  /* @__PURE__ */ jsx(Box, { className: "p-4", children: slotContent })
46323
46335
  ]
46324
46336
  }
@@ -46362,6 +46374,7 @@ function UISlotComponent({
46362
46374
  sourceTrait
46363
46375
  }) {
46364
46376
  const { slots, clear } = useUISlots();
46377
+ const eventBus = useEventBus();
46365
46378
  const suspenseConfig = useContext(SuspenseConfigContext);
46366
46379
  const contained = useContext(SlotContainedContext);
46367
46380
  const content = slots[slot];
@@ -46408,6 +46421,10 @@ function UISlotComponent({
46408
46421
  return null;
46409
46422
  }
46410
46423
  const handleDismiss = () => {
46424
+ if (slot === "modal" || slot === "drawer") {
46425
+ eventBus.emit("UI:CLOSE");
46426
+ eventBus.emit("UI:CANCEL");
46427
+ }
46411
46428
  clear(slot);
46412
46429
  };
46413
46430
  if (portal) {
@@ -46457,7 +46474,8 @@ function getOrCreatePortalRoot() {
46457
46474
  }
46458
46475
  function CompiledPortal({ slot, className, pattern, sourceTrait, children }) {
46459
46476
  const [portalRoot, setPortalRoot] = useState(null);
46460
- const eventBus = useUISlots();
46477
+ const slotsBus = useUISlots();
46478
+ const eventBus = useEventBus();
46461
46479
  useEffect(() => {
46462
46480
  setPortalRoot(getOrCreatePortalRoot());
46463
46481
  }, []);
@@ -46465,7 +46483,11 @@ function CompiledPortal({ slot, className, pattern, sourceTrait, children }) {
46465
46483
  if (portalRoot) getOrCreatePortalRoot();
46466
46484
  });
46467
46485
  const handleDismiss = () => {
46468
- eventBus.clear(slot);
46486
+ if (slot === "modal" || slot === "drawer") {
46487
+ eventBus.emit("UI:CLOSE");
46488
+ eventBus.emit("UI:CANCEL");
46489
+ }
46490
+ slotsBus.clear(slot);
46469
46491
  };
46470
46492
  if (!portalRoot) return null;
46471
46493
  const slotId = `slot-${slot}`;
@@ -46813,6 +46835,7 @@ var init_UISlotRenderer = __esm({
46813
46835
  init_Toast();
46814
46836
  init_Box();
46815
46837
  init_Typography();
46838
+ init_useEventBus();
46816
46839
  init_cn();
46817
46840
  init_ErrorBoundary();
46818
46841
  init_Skeleton();
@@ -37163,18 +37163,24 @@ function renderContainedPortal(slot, content, onDismiss) {
37163
37163
  style: { minWidth: "520px", maxWidth: "700px", maxHeight: "80%" },
37164
37164
  onClick: (e) => e.stopPropagation(),
37165
37165
  children: [
37166
- content.props.title ? /* @__PURE__ */ jsxRuntime.jsxs(exports.Box, { className: "flex items-center justify-between p-4 border-b border-border", children: [
37167
- /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "h3", className: "text-lg font-semibold", children: String(content.props.title) }),
37166
+ /* @__PURE__ */ jsxRuntime.jsxs(exports.Box, { className: cn(
37167
+ "flex items-center p-4",
37168
+ content.props.title ? "justify-between border-b border-border" : "justify-end"
37169
+ ), children: [
37170
+ content.props.title ? /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "h3", className: "text-lg font-semibold", children: String(content.props.title) }) : null,
37168
37171
  /* @__PURE__ */ jsxRuntime.jsx(
37169
37172
  exports.Box,
37170
37173
  {
37171
37174
  as: "button",
37172
37175
  className: "text-muted-foreground hover:text-foreground cursor-pointer",
37173
37176
  onClick: onDismiss,
37177
+ "data-event": "CLOSE",
37178
+ "data-testid": "action-CLOSE",
37179
+ "aria-label": "Close modal",
37174
37180
  children: "\u2715"
37175
37181
  }
37176
37182
  )
37177
- ] }) : null,
37183
+ ] }),
37178
37184
  /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: "flex-1 overflow-auto p-4", children: slotContent })
37179
37185
  ]
37180
37186
  }
@@ -37199,18 +37205,24 @@ function renderContainedPortal(slot, content, onDismiss) {
37199
37205
  ),
37200
37206
  onClick: (e) => e.stopPropagation(),
37201
37207
  children: [
37202
- content.props.title ? /* @__PURE__ */ jsxRuntime.jsxs(exports.Box, { className: "flex items-center justify-between p-4 border-b border-border", children: [
37203
- /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "h3", className: "text-lg font-semibold", children: String(content.props.title) }),
37208
+ /* @__PURE__ */ jsxRuntime.jsxs(exports.Box, { className: cn(
37209
+ "flex items-center p-4",
37210
+ content.props.title ? "justify-between border-b border-border" : "justify-end"
37211
+ ), children: [
37212
+ content.props.title ? /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "h3", className: "text-lg font-semibold", children: String(content.props.title) }) : null,
37204
37213
  /* @__PURE__ */ jsxRuntime.jsx(
37205
37214
  exports.Box,
37206
37215
  {
37207
37216
  as: "button",
37208
37217
  className: "text-muted-foreground hover:text-foreground cursor-pointer",
37209
37218
  onClick: onDismiss,
37219
+ "data-event": "CLOSE",
37220
+ "data-testid": "action-CLOSE",
37221
+ "aria-label": "Close drawer",
37210
37222
  children: "\u2715"
37211
37223
  }
37212
37224
  )
37213
- ] }) : null,
37225
+ ] }),
37214
37226
  /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: "p-4", children: slotContent })
37215
37227
  ]
37216
37228
  }
@@ -37254,6 +37266,7 @@ function UISlotComponent({
37254
37266
  sourceTrait
37255
37267
  }) {
37256
37268
  const { slots, clear } = context.useUISlots();
37269
+ const eventBus = useEventBus();
37257
37270
  const suspenseConfig = React110.useContext(SuspenseConfigContext);
37258
37271
  const contained = React110.useContext(SlotContainedContext);
37259
37272
  const content = slots[slot];
@@ -37300,6 +37313,10 @@ function UISlotComponent({
37300
37313
  return null;
37301
37314
  }
37302
37315
  const handleDismiss = () => {
37316
+ if (slot === "modal" || slot === "drawer") {
37317
+ eventBus.emit("UI:CLOSE");
37318
+ eventBus.emit("UI:CANCEL");
37319
+ }
37303
37320
  clear(slot);
37304
37321
  };
37305
37322
  if (portal) {
@@ -37349,7 +37366,8 @@ function getOrCreatePortalRoot() {
37349
37366
  }
37350
37367
  function CompiledPortal({ slot, className, pattern, sourceTrait, children }) {
37351
37368
  const [portalRoot, setPortalRoot] = React110.useState(null);
37352
- const eventBus = context.useUISlots();
37369
+ const slotsBus = context.useUISlots();
37370
+ const eventBus = useEventBus();
37353
37371
  React110.useEffect(() => {
37354
37372
  setPortalRoot(getOrCreatePortalRoot());
37355
37373
  }, []);
@@ -37357,7 +37375,11 @@ function CompiledPortal({ slot, className, pattern, sourceTrait, children }) {
37357
37375
  if (portalRoot) getOrCreatePortalRoot();
37358
37376
  });
37359
37377
  const handleDismiss = () => {
37360
- eventBus.clear(slot);
37378
+ if (slot === "modal" || slot === "drawer") {
37379
+ eventBus.emit("UI:CLOSE");
37380
+ eventBus.emit("UI:CANCEL");
37381
+ }
37382
+ slotsBus.clear(slot);
37361
37383
  };
37362
37384
  if (!portalRoot) return null;
37363
37385
  const slotId = `slot-${slot}`;
@@ -37704,6 +37726,7 @@ var init_UISlotRenderer = __esm({
37704
37726
  init_Toast();
37705
37727
  init_Box();
37706
37728
  init_Typography();
37729
+ init_useEventBus();
37707
37730
  init_cn();
37708
37731
  init_ErrorBoundary();
37709
37732
  init_Skeleton();
@@ -37118,18 +37118,24 @@ function renderContainedPortal(slot, content, onDismiss) {
37118
37118
  style: { minWidth: "520px", maxWidth: "700px", maxHeight: "80%" },
37119
37119
  onClick: (e) => e.stopPropagation(),
37120
37120
  children: [
37121
- content.props.title ? /* @__PURE__ */ jsxs(Box, { className: "flex items-center justify-between p-4 border-b border-border", children: [
37122
- /* @__PURE__ */ jsx(Typography, { variant: "h3", className: "text-lg font-semibold", children: String(content.props.title) }),
37121
+ /* @__PURE__ */ jsxs(Box, { className: cn(
37122
+ "flex items-center p-4",
37123
+ content.props.title ? "justify-between border-b border-border" : "justify-end"
37124
+ ), children: [
37125
+ content.props.title ? /* @__PURE__ */ jsx(Typography, { variant: "h3", className: "text-lg font-semibold", children: String(content.props.title) }) : null,
37123
37126
  /* @__PURE__ */ jsx(
37124
37127
  Box,
37125
37128
  {
37126
37129
  as: "button",
37127
37130
  className: "text-muted-foreground hover:text-foreground cursor-pointer",
37128
37131
  onClick: onDismiss,
37132
+ "data-event": "CLOSE",
37133
+ "data-testid": "action-CLOSE",
37134
+ "aria-label": "Close modal",
37129
37135
  children: "\u2715"
37130
37136
  }
37131
37137
  )
37132
- ] }) : null,
37138
+ ] }),
37133
37139
  /* @__PURE__ */ jsx(Box, { className: "flex-1 overflow-auto p-4", children: slotContent })
37134
37140
  ]
37135
37141
  }
@@ -37154,18 +37160,24 @@ function renderContainedPortal(slot, content, onDismiss) {
37154
37160
  ),
37155
37161
  onClick: (e) => e.stopPropagation(),
37156
37162
  children: [
37157
- content.props.title ? /* @__PURE__ */ jsxs(Box, { className: "flex items-center justify-between p-4 border-b border-border", children: [
37158
- /* @__PURE__ */ jsx(Typography, { variant: "h3", className: "text-lg font-semibold", children: String(content.props.title) }),
37163
+ /* @__PURE__ */ jsxs(Box, { className: cn(
37164
+ "flex items-center p-4",
37165
+ content.props.title ? "justify-between border-b border-border" : "justify-end"
37166
+ ), children: [
37167
+ content.props.title ? /* @__PURE__ */ jsx(Typography, { variant: "h3", className: "text-lg font-semibold", children: String(content.props.title) }) : null,
37159
37168
  /* @__PURE__ */ jsx(
37160
37169
  Box,
37161
37170
  {
37162
37171
  as: "button",
37163
37172
  className: "text-muted-foreground hover:text-foreground cursor-pointer",
37164
37173
  onClick: onDismiss,
37174
+ "data-event": "CLOSE",
37175
+ "data-testid": "action-CLOSE",
37176
+ "aria-label": "Close drawer",
37165
37177
  children: "\u2715"
37166
37178
  }
37167
37179
  )
37168
- ] }) : null,
37180
+ ] }),
37169
37181
  /* @__PURE__ */ jsx(Box, { className: "p-4", children: slotContent })
37170
37182
  ]
37171
37183
  }
@@ -37209,6 +37221,7 @@ function UISlotComponent({
37209
37221
  sourceTrait
37210
37222
  }) {
37211
37223
  const { slots, clear } = useUISlots();
37224
+ const eventBus = useEventBus();
37212
37225
  const suspenseConfig = useContext(SuspenseConfigContext);
37213
37226
  const contained = useContext(SlotContainedContext);
37214
37227
  const content = slots[slot];
@@ -37255,6 +37268,10 @@ function UISlotComponent({
37255
37268
  return null;
37256
37269
  }
37257
37270
  const handleDismiss = () => {
37271
+ if (slot === "modal" || slot === "drawer") {
37272
+ eventBus.emit("UI:CLOSE");
37273
+ eventBus.emit("UI:CANCEL");
37274
+ }
37258
37275
  clear(slot);
37259
37276
  };
37260
37277
  if (portal) {
@@ -37304,7 +37321,8 @@ function getOrCreatePortalRoot() {
37304
37321
  }
37305
37322
  function CompiledPortal({ slot, className, pattern, sourceTrait, children }) {
37306
37323
  const [portalRoot, setPortalRoot] = useState(null);
37307
- const eventBus = useUISlots();
37324
+ const slotsBus = useUISlots();
37325
+ const eventBus = useEventBus();
37308
37326
  useEffect(() => {
37309
37327
  setPortalRoot(getOrCreatePortalRoot());
37310
37328
  }, []);
@@ -37312,7 +37330,11 @@ function CompiledPortal({ slot, className, pattern, sourceTrait, children }) {
37312
37330
  if (portalRoot) getOrCreatePortalRoot();
37313
37331
  });
37314
37332
  const handleDismiss = () => {
37315
- eventBus.clear(slot);
37333
+ if (slot === "modal" || slot === "drawer") {
37334
+ eventBus.emit("UI:CLOSE");
37335
+ eventBus.emit("UI:CANCEL");
37336
+ }
37337
+ slotsBus.clear(slot);
37316
37338
  };
37317
37339
  if (!portalRoot) return null;
37318
37340
  const slotId = `slot-${slot}`;
@@ -37659,6 +37681,7 @@ var init_UISlotRenderer = __esm({
37659
37681
  init_Toast();
37660
37682
  init_Box();
37661
37683
  init_Typography();
37684
+ init_useEventBus();
37662
37685
  init_cn();
37663
37686
  init_ErrorBoundary();
37664
37687
  init_Skeleton();
@@ -155,8 +155,13 @@ export interface FormProps extends Omit<React.FormHTMLAttributes<HTMLFormElement
155
155
  className?: string;
156
156
  /** Entity type name or schema object. When OrbitalEntity, fields are auto-derived if not provided. */
157
157
  entity?: string | OrbitalEntity | readonly Record<string, unknown>[];
158
- /** Form mode - 'create' for new records, 'edit' for updating existing */
159
- mode?: "create" | "edit";
158
+ /**
159
+ * Form mode — 'create' for new records, 'edit' for updating existing.
160
+ * Accepts `string` so schema-driven callers (whose `config.mode` is typed
161
+ * as `string` per the trait's declared config block) compile cleanly. The
162
+ * runtime treats anything other than 'edit' as 'create'.
163
+ */
164
+ mode?: "create" | "edit" | string;
160
165
  /** Fields definition (schema format) - accepts readonly for generated const arrays */
161
166
  fields: readonly Readonly<SchemaField>[];
162
167
  /** Initial form data */
@@ -37672,18 +37672,24 @@ function renderContainedPortal(slot, content, onDismiss) {
37672
37672
  style: { minWidth: "520px", maxWidth: "700px", maxHeight: "80%" },
37673
37673
  onClick: (e) => e.stopPropagation(),
37674
37674
  children: [
37675
- content.props.title ? /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex items-center justify-between p-4 border-b border-border", children: [
37676
- /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h3", className: "text-lg font-semibold", children: String(content.props.title) }),
37675
+ /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: cn(
37676
+ "flex items-center p-4",
37677
+ content.props.title ? "justify-between border-b border-border" : "justify-end"
37678
+ ), children: [
37679
+ content.props.title ? /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h3", className: "text-lg font-semibold", children: String(content.props.title) }) : null,
37677
37680
  /* @__PURE__ */ jsxRuntime.jsx(
37678
37681
  Box,
37679
37682
  {
37680
37683
  as: "button",
37681
37684
  className: "text-muted-foreground hover:text-foreground cursor-pointer",
37682
37685
  onClick: onDismiss,
37686
+ "data-event": "CLOSE",
37687
+ "data-testid": "action-CLOSE",
37688
+ "aria-label": "Close modal",
37683
37689
  children: "\u2715"
37684
37690
  }
37685
37691
  )
37686
- ] }) : null,
37692
+ ] }),
37687
37693
  /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex-1 overflow-auto p-4", children: slotContent })
37688
37694
  ]
37689
37695
  }
@@ -37708,18 +37714,24 @@ function renderContainedPortal(slot, content, onDismiss) {
37708
37714
  ),
37709
37715
  onClick: (e) => e.stopPropagation(),
37710
37716
  children: [
37711
- content.props.title ? /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex items-center justify-between p-4 border-b border-border", children: [
37712
- /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h3", className: "text-lg font-semibold", children: String(content.props.title) }),
37717
+ /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: cn(
37718
+ "flex items-center p-4",
37719
+ content.props.title ? "justify-between border-b border-border" : "justify-end"
37720
+ ), children: [
37721
+ content.props.title ? /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h3", className: "text-lg font-semibold", children: String(content.props.title) }) : null,
37713
37722
  /* @__PURE__ */ jsxRuntime.jsx(
37714
37723
  Box,
37715
37724
  {
37716
37725
  as: "button",
37717
37726
  className: "text-muted-foreground hover:text-foreground cursor-pointer",
37718
37727
  onClick: onDismiss,
37728
+ "data-event": "CLOSE",
37729
+ "data-testid": "action-CLOSE",
37730
+ "aria-label": "Close drawer",
37719
37731
  children: "\u2715"
37720
37732
  }
37721
37733
  )
37722
- ] }) : null,
37734
+ ] }),
37723
37735
  /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "p-4", children: slotContent })
37724
37736
  ]
37725
37737
  }
@@ -37763,6 +37775,7 @@ function UISlotComponent({
37763
37775
  sourceTrait
37764
37776
  }) {
37765
37777
  const { slots, clear } = context.useUISlots();
37778
+ const eventBus = useEventBus();
37766
37779
  const suspenseConfig = React115.useContext(SuspenseConfigContext);
37767
37780
  const contained = React115.useContext(SlotContainedContext);
37768
37781
  const content = slots[slot];
@@ -37809,6 +37822,10 @@ function UISlotComponent({
37809
37822
  return null;
37810
37823
  }
37811
37824
  const handleDismiss = () => {
37825
+ if (slot === "modal" || slot === "drawer") {
37826
+ eventBus.emit("UI:CLOSE");
37827
+ eventBus.emit("UI:CANCEL");
37828
+ }
37812
37829
  clear(slot);
37813
37830
  };
37814
37831
  if (portal) {
@@ -37858,7 +37875,8 @@ function getOrCreatePortalRoot() {
37858
37875
  }
37859
37876
  function CompiledPortal({ slot, className, pattern, sourceTrait, children }) {
37860
37877
  const [portalRoot, setPortalRoot] = React115.useState(null);
37861
- const eventBus = context.useUISlots();
37878
+ const slotsBus = context.useUISlots();
37879
+ const eventBus = useEventBus();
37862
37880
  React115.useEffect(() => {
37863
37881
  setPortalRoot(getOrCreatePortalRoot());
37864
37882
  }, []);
@@ -37866,7 +37884,11 @@ function CompiledPortal({ slot, className, pattern, sourceTrait, children }) {
37866
37884
  if (portalRoot) getOrCreatePortalRoot();
37867
37885
  });
37868
37886
  const handleDismiss = () => {
37869
- eventBus.clear(slot);
37887
+ if (slot === "modal" || slot === "drawer") {
37888
+ eventBus.emit("UI:CLOSE");
37889
+ eventBus.emit("UI:CANCEL");
37890
+ }
37891
+ slotsBus.clear(slot);
37870
37892
  };
37871
37893
  if (!portalRoot) return null;
37872
37894
  const slotId = `slot-${slot}`;
@@ -38213,6 +38235,7 @@ var init_UISlotRenderer = __esm({
38213
38235
  init_Toast();
38214
38236
  init_Box();
38215
38237
  init_Typography();
38238
+ init_useEventBus();
38216
38239
  init_cn();
38217
38240
  init_ErrorBoundary();
38218
38241
  init_Skeleton();
@@ -37627,18 +37627,24 @@ function renderContainedPortal(slot, content, onDismiss) {
37627
37627
  style: { minWidth: "520px", maxWidth: "700px", maxHeight: "80%" },
37628
37628
  onClick: (e) => e.stopPropagation(),
37629
37629
  children: [
37630
- content.props.title ? /* @__PURE__ */ jsxs(Box, { className: "flex items-center justify-between p-4 border-b border-border", children: [
37631
- /* @__PURE__ */ jsx(Typography, { variant: "h3", className: "text-lg font-semibold", children: String(content.props.title) }),
37630
+ /* @__PURE__ */ jsxs(Box, { className: cn(
37631
+ "flex items-center p-4",
37632
+ content.props.title ? "justify-between border-b border-border" : "justify-end"
37633
+ ), children: [
37634
+ content.props.title ? /* @__PURE__ */ jsx(Typography, { variant: "h3", className: "text-lg font-semibold", children: String(content.props.title) }) : null,
37632
37635
  /* @__PURE__ */ jsx(
37633
37636
  Box,
37634
37637
  {
37635
37638
  as: "button",
37636
37639
  className: "text-muted-foreground hover:text-foreground cursor-pointer",
37637
37640
  onClick: onDismiss,
37641
+ "data-event": "CLOSE",
37642
+ "data-testid": "action-CLOSE",
37643
+ "aria-label": "Close modal",
37638
37644
  children: "\u2715"
37639
37645
  }
37640
37646
  )
37641
- ] }) : null,
37647
+ ] }),
37642
37648
  /* @__PURE__ */ jsx(Box, { className: "flex-1 overflow-auto p-4", children: slotContent })
37643
37649
  ]
37644
37650
  }
@@ -37663,18 +37669,24 @@ function renderContainedPortal(slot, content, onDismiss) {
37663
37669
  ),
37664
37670
  onClick: (e) => e.stopPropagation(),
37665
37671
  children: [
37666
- content.props.title ? /* @__PURE__ */ jsxs(Box, { className: "flex items-center justify-between p-4 border-b border-border", children: [
37667
- /* @__PURE__ */ jsx(Typography, { variant: "h3", className: "text-lg font-semibold", children: String(content.props.title) }),
37672
+ /* @__PURE__ */ jsxs(Box, { className: cn(
37673
+ "flex items-center p-4",
37674
+ content.props.title ? "justify-between border-b border-border" : "justify-end"
37675
+ ), children: [
37676
+ content.props.title ? /* @__PURE__ */ jsx(Typography, { variant: "h3", className: "text-lg font-semibold", children: String(content.props.title) }) : null,
37668
37677
  /* @__PURE__ */ jsx(
37669
37678
  Box,
37670
37679
  {
37671
37680
  as: "button",
37672
37681
  className: "text-muted-foreground hover:text-foreground cursor-pointer",
37673
37682
  onClick: onDismiss,
37683
+ "data-event": "CLOSE",
37684
+ "data-testid": "action-CLOSE",
37685
+ "aria-label": "Close drawer",
37674
37686
  children: "\u2715"
37675
37687
  }
37676
37688
  )
37677
- ] }) : null,
37689
+ ] }),
37678
37690
  /* @__PURE__ */ jsx(Box, { className: "p-4", children: slotContent })
37679
37691
  ]
37680
37692
  }
@@ -37718,6 +37730,7 @@ function UISlotComponent({
37718
37730
  sourceTrait
37719
37731
  }) {
37720
37732
  const { slots, clear } = useUISlots();
37733
+ const eventBus = useEventBus();
37721
37734
  const suspenseConfig = useContext(SuspenseConfigContext);
37722
37735
  const contained = useContext(SlotContainedContext);
37723
37736
  const content = slots[slot];
@@ -37764,6 +37777,10 @@ function UISlotComponent({
37764
37777
  return null;
37765
37778
  }
37766
37779
  const handleDismiss = () => {
37780
+ if (slot === "modal" || slot === "drawer") {
37781
+ eventBus.emit("UI:CLOSE");
37782
+ eventBus.emit("UI:CANCEL");
37783
+ }
37767
37784
  clear(slot);
37768
37785
  };
37769
37786
  if (portal) {
@@ -37813,7 +37830,8 @@ function getOrCreatePortalRoot() {
37813
37830
  }
37814
37831
  function CompiledPortal({ slot, className, pattern, sourceTrait, children }) {
37815
37832
  const [portalRoot, setPortalRoot] = useState(null);
37816
- const eventBus = useUISlots();
37833
+ const slotsBus = useUISlots();
37834
+ const eventBus = useEventBus();
37817
37835
  useEffect(() => {
37818
37836
  setPortalRoot(getOrCreatePortalRoot());
37819
37837
  }, []);
@@ -37821,7 +37839,11 @@ function CompiledPortal({ slot, className, pattern, sourceTrait, children }) {
37821
37839
  if (portalRoot) getOrCreatePortalRoot();
37822
37840
  });
37823
37841
  const handleDismiss = () => {
37824
- eventBus.clear(slot);
37842
+ if (slot === "modal" || slot === "drawer") {
37843
+ eventBus.emit("UI:CLOSE");
37844
+ eventBus.emit("UI:CANCEL");
37845
+ }
37846
+ slotsBus.clear(slot);
37825
37847
  };
37826
37848
  if (!portalRoot) return null;
37827
37849
  const slotId = `slot-${slot}`;
@@ -38168,6 +38190,7 @@ var init_UISlotRenderer = __esm({
38168
38190
  init_Toast();
38169
38191
  init_Box();
38170
38192
  init_Typography();
38193
+ init_useEventBus();
38171
38194
  init_cn();
38172
38195
  init_ErrorBoundary();
38173
38196
  init_Skeleton();
@@ -37258,18 +37258,24 @@ function renderContainedPortal(slot, content, onDismiss) {
37258
37258
  style: { minWidth: "520px", maxWidth: "700px", maxHeight: "80%" },
37259
37259
  onClick: (e) => e.stopPropagation(),
37260
37260
  children: [
37261
- content.props.title ? /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex items-center justify-between p-4 border-b border-border", children: [
37262
- /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h3", className: "text-lg font-semibold", children: String(content.props.title) }),
37261
+ /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: cn(
37262
+ "flex items-center p-4",
37263
+ content.props.title ? "justify-between border-b border-border" : "justify-end"
37264
+ ), children: [
37265
+ content.props.title ? /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h3", className: "text-lg font-semibold", children: String(content.props.title) }) : null,
37263
37266
  /* @__PURE__ */ jsxRuntime.jsx(
37264
37267
  Box,
37265
37268
  {
37266
37269
  as: "button",
37267
37270
  className: "text-muted-foreground hover:text-foreground cursor-pointer",
37268
37271
  onClick: onDismiss,
37272
+ "data-event": "CLOSE",
37273
+ "data-testid": "action-CLOSE",
37274
+ "aria-label": "Close modal",
37269
37275
  children: "\u2715"
37270
37276
  }
37271
37277
  )
37272
- ] }) : null,
37278
+ ] }),
37273
37279
  /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex-1 overflow-auto p-4", children: slotContent })
37274
37280
  ]
37275
37281
  }
@@ -37294,18 +37300,24 @@ function renderContainedPortal(slot, content, onDismiss) {
37294
37300
  ),
37295
37301
  onClick: (e) => e.stopPropagation(),
37296
37302
  children: [
37297
- content.props.title ? /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex items-center justify-between p-4 border-b border-border", children: [
37298
- /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h3", className: "text-lg font-semibold", children: String(content.props.title) }),
37303
+ /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: cn(
37304
+ "flex items-center p-4",
37305
+ content.props.title ? "justify-between border-b border-border" : "justify-end"
37306
+ ), children: [
37307
+ content.props.title ? /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h3", className: "text-lg font-semibold", children: String(content.props.title) }) : null,
37299
37308
  /* @__PURE__ */ jsxRuntime.jsx(
37300
37309
  Box,
37301
37310
  {
37302
37311
  as: "button",
37303
37312
  className: "text-muted-foreground hover:text-foreground cursor-pointer",
37304
37313
  onClick: onDismiss,
37314
+ "data-event": "CLOSE",
37315
+ "data-testid": "action-CLOSE",
37316
+ "aria-label": "Close drawer",
37305
37317
  children: "\u2715"
37306
37318
  }
37307
37319
  )
37308
- ] }) : null,
37320
+ ] }),
37309
37321
  /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "p-4", children: slotContent })
37310
37322
  ]
37311
37323
  }
@@ -37349,6 +37361,7 @@ function UISlotComponent({
37349
37361
  sourceTrait
37350
37362
  }) {
37351
37363
  const { slots, clear } = context.useUISlots();
37364
+ const eventBus = useEventBus();
37352
37365
  const suspenseConfig = React115.useContext(SuspenseConfigContext);
37353
37366
  const contained = React115.useContext(SlotContainedContext);
37354
37367
  const content = slots[slot];
@@ -37395,6 +37408,10 @@ function UISlotComponent({
37395
37408
  return null;
37396
37409
  }
37397
37410
  const handleDismiss = () => {
37411
+ if (slot === "modal" || slot === "drawer") {
37412
+ eventBus.emit("UI:CLOSE");
37413
+ eventBus.emit("UI:CANCEL");
37414
+ }
37398
37415
  clear(slot);
37399
37416
  };
37400
37417
  if (portal) {
@@ -37444,7 +37461,8 @@ function getOrCreatePortalRoot() {
37444
37461
  }
37445
37462
  function CompiledPortal({ slot, className, pattern, sourceTrait, children }) {
37446
37463
  const [portalRoot, setPortalRoot] = React115.useState(null);
37447
- const eventBus = context.useUISlots();
37464
+ const slotsBus = context.useUISlots();
37465
+ const eventBus = useEventBus();
37448
37466
  React115.useEffect(() => {
37449
37467
  setPortalRoot(getOrCreatePortalRoot());
37450
37468
  }, []);
@@ -37452,7 +37470,11 @@ function CompiledPortal({ slot, className, pattern, sourceTrait, children }) {
37452
37470
  if (portalRoot) getOrCreatePortalRoot();
37453
37471
  });
37454
37472
  const handleDismiss = () => {
37455
- eventBus.clear(slot);
37473
+ if (slot === "modal" || slot === "drawer") {
37474
+ eventBus.emit("UI:CLOSE");
37475
+ eventBus.emit("UI:CANCEL");
37476
+ }
37477
+ slotsBus.clear(slot);
37456
37478
  };
37457
37479
  if (!portalRoot) return null;
37458
37480
  const slotId = `slot-${slot}`;
@@ -37799,6 +37821,7 @@ var init_UISlotRenderer = __esm({
37799
37821
  init_Toast();
37800
37822
  init_Box();
37801
37823
  init_Typography();
37824
+ init_useEventBus();
37802
37825
  init_cn();
37803
37826
  init_ErrorBoundary();
37804
37827
  init_Skeleton();
@@ -37213,18 +37213,24 @@ function renderContainedPortal(slot, content, onDismiss) {
37213
37213
  style: { minWidth: "520px", maxWidth: "700px", maxHeight: "80%" },
37214
37214
  onClick: (e) => e.stopPropagation(),
37215
37215
  children: [
37216
- content.props.title ? /* @__PURE__ */ jsxs(Box, { className: "flex items-center justify-between p-4 border-b border-border", children: [
37217
- /* @__PURE__ */ jsx(Typography, { variant: "h3", className: "text-lg font-semibold", children: String(content.props.title) }),
37216
+ /* @__PURE__ */ jsxs(Box, { className: cn(
37217
+ "flex items-center p-4",
37218
+ content.props.title ? "justify-between border-b border-border" : "justify-end"
37219
+ ), children: [
37220
+ content.props.title ? /* @__PURE__ */ jsx(Typography, { variant: "h3", className: "text-lg font-semibold", children: String(content.props.title) }) : null,
37218
37221
  /* @__PURE__ */ jsx(
37219
37222
  Box,
37220
37223
  {
37221
37224
  as: "button",
37222
37225
  className: "text-muted-foreground hover:text-foreground cursor-pointer",
37223
37226
  onClick: onDismiss,
37227
+ "data-event": "CLOSE",
37228
+ "data-testid": "action-CLOSE",
37229
+ "aria-label": "Close modal",
37224
37230
  children: "\u2715"
37225
37231
  }
37226
37232
  )
37227
- ] }) : null,
37233
+ ] }),
37228
37234
  /* @__PURE__ */ jsx(Box, { className: "flex-1 overflow-auto p-4", children: slotContent })
37229
37235
  ]
37230
37236
  }
@@ -37249,18 +37255,24 @@ function renderContainedPortal(slot, content, onDismiss) {
37249
37255
  ),
37250
37256
  onClick: (e) => e.stopPropagation(),
37251
37257
  children: [
37252
- content.props.title ? /* @__PURE__ */ jsxs(Box, { className: "flex items-center justify-between p-4 border-b border-border", children: [
37253
- /* @__PURE__ */ jsx(Typography, { variant: "h3", className: "text-lg font-semibold", children: String(content.props.title) }),
37258
+ /* @__PURE__ */ jsxs(Box, { className: cn(
37259
+ "flex items-center p-4",
37260
+ content.props.title ? "justify-between border-b border-border" : "justify-end"
37261
+ ), children: [
37262
+ content.props.title ? /* @__PURE__ */ jsx(Typography, { variant: "h3", className: "text-lg font-semibold", children: String(content.props.title) }) : null,
37254
37263
  /* @__PURE__ */ jsx(
37255
37264
  Box,
37256
37265
  {
37257
37266
  as: "button",
37258
37267
  className: "text-muted-foreground hover:text-foreground cursor-pointer",
37259
37268
  onClick: onDismiss,
37269
+ "data-event": "CLOSE",
37270
+ "data-testid": "action-CLOSE",
37271
+ "aria-label": "Close drawer",
37260
37272
  children: "\u2715"
37261
37273
  }
37262
37274
  )
37263
- ] }) : null,
37275
+ ] }),
37264
37276
  /* @__PURE__ */ jsx(Box, { className: "p-4", children: slotContent })
37265
37277
  ]
37266
37278
  }
@@ -37304,6 +37316,7 @@ function UISlotComponent({
37304
37316
  sourceTrait
37305
37317
  }) {
37306
37318
  const { slots, clear } = useUISlots();
37319
+ const eventBus = useEventBus();
37307
37320
  const suspenseConfig = useContext(SuspenseConfigContext);
37308
37321
  const contained = useContext(SlotContainedContext);
37309
37322
  const content = slots[slot];
@@ -37350,6 +37363,10 @@ function UISlotComponent({
37350
37363
  return null;
37351
37364
  }
37352
37365
  const handleDismiss = () => {
37366
+ if (slot === "modal" || slot === "drawer") {
37367
+ eventBus.emit("UI:CLOSE");
37368
+ eventBus.emit("UI:CANCEL");
37369
+ }
37353
37370
  clear(slot);
37354
37371
  };
37355
37372
  if (portal) {
@@ -37399,7 +37416,8 @@ function getOrCreatePortalRoot() {
37399
37416
  }
37400
37417
  function CompiledPortal({ slot, className, pattern, sourceTrait, children }) {
37401
37418
  const [portalRoot, setPortalRoot] = useState(null);
37402
- const eventBus = useUISlots();
37419
+ const slotsBus = useUISlots();
37420
+ const eventBus = useEventBus();
37403
37421
  useEffect(() => {
37404
37422
  setPortalRoot(getOrCreatePortalRoot());
37405
37423
  }, []);
@@ -37407,7 +37425,11 @@ function CompiledPortal({ slot, className, pattern, sourceTrait, children }) {
37407
37425
  if (portalRoot) getOrCreatePortalRoot();
37408
37426
  });
37409
37427
  const handleDismiss = () => {
37410
- eventBus.clear(slot);
37428
+ if (slot === "modal" || slot === "drawer") {
37429
+ eventBus.emit("UI:CLOSE");
37430
+ eventBus.emit("UI:CANCEL");
37431
+ }
37432
+ slotsBus.clear(slot);
37411
37433
  };
37412
37434
  if (!portalRoot) return null;
37413
37435
  const slotId = `slot-${slot}`;
@@ -37754,6 +37776,7 @@ var init_UISlotRenderer = __esm({
37754
37776
  init_Toast();
37755
37777
  init_Box();
37756
37778
  init_Typography();
37779
+ init_useEventBus();
37757
37780
  init_cn();
37758
37781
  init_ErrorBoundary();
37759
37782
  init_Skeleton();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almadar/ui",
3
- "version": "4.3.0",
3
+ "version": "4.4.0",
4
4
  "description": "React UI components, hooks, and providers for Almadar",
5
5
  "type": "module",
6
6
  "main": "./dist/components/index.js",