@bizapps/ui 1.4.2 → 1.5.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.
package/dist/main.cjs CHANGED
@@ -5143,6 +5143,8 @@ function AbilityProvider({ children, permissions }) {
5143
5143
  const [permissionSet, setPermissionSet] = react.useState(
5144
5144
  () => new Set(permissions ?? [])
5145
5145
  );
5146
+ const [imperativelyResolved, setImperativelyResolved] = react.useState(false);
5147
+ const status = permissions !== void 0 || imperativelyResolved ? "ready" : "loading";
5146
5148
  const can = react.useCallback(
5147
5149
  (perms, mode = "any") => {
5148
5150
  const list = Array.isArray(perms) ? perms : [perms];
@@ -5157,21 +5159,23 @@ function AbilityProvider({ children, permissions }) {
5157
5159
  );
5158
5160
  const setAbilities = react.useCallback((perms) => {
5159
5161
  setPermissionSet(new Set(perms));
5162
+ setImperativelyResolved(true);
5160
5163
  }, []);
5161
5164
  const clearAbilities = react.useCallback(() => {
5162
5165
  setPermissionSet(/* @__PURE__ */ new Set());
5166
+ setImperativelyResolved(true);
5163
5167
  }, []);
5164
- const syncedKey = react.useRef(permissions ? permissions.join("|") : null);
5168
+ const permissionKey = permissions === void 0 ? null : [...permissions].sort().join("|");
5169
+ const syncedKey = react.useRef(permissionKey);
5165
5170
  react.useEffect(() => {
5166
- if (permissions === void 0) return;
5167
- const key = permissions.join("|");
5168
- if (key === syncedKey.current) return;
5169
- syncedKey.current = key;
5171
+ if (permissionKey === null) return;
5172
+ if (permissionKey === syncedKey.current) return;
5173
+ syncedKey.current = permissionKey;
5170
5174
  setPermissionSet(new Set(permissions));
5171
- }, [permissions]);
5175
+ }, [permissionKey, permissions]);
5172
5176
  const value = react.useMemo(
5173
- () => ({ can, setAbilities, clearAbilities }),
5174
- [can, setAbilities, clearAbilities]
5177
+ () => ({ can, setAbilities, clearAbilities, status }),
5178
+ [can, setAbilities, clearAbilities, status]
5175
5179
  );
5176
5180
  return /* @__PURE__ */ jsxRuntime.jsx(AbilityContext.Provider, { value, children });
5177
5181
  }
@@ -5186,18 +5190,173 @@ function useCan(permissions, mode = "any") {
5186
5190
  const { can } = useAbility();
5187
5191
  return can(permissions, mode);
5188
5192
  }
5189
- function Can({ permission, mode = "any", negate = false, fallback = null, children }) {
5190
- const { can } = useAbility();
5191
- const hasPermission = can(permission, mode);
5193
+ function useAbilityStatus() {
5194
+ return useAbility().status;
5195
+ }
5196
+
5197
+ // src/components/authorization/permissions.generated.ts
5198
+ var KNOWN_PERMISSIONS = [];
5199
+
5200
+ // src/components/authorization/permission-catalog.ts
5201
+ var CATALOG = new Set(KNOWN_PERMISSIONS);
5202
+ var warned = /* @__PURE__ */ new Set();
5203
+ function warnUnknownPermission(permission) {
5204
+ if (process.env.NODE_ENV === "production") return;
5205
+ if (CATALOG.size === 0) return;
5206
+ const requested = Array.isArray(permission) ? permission : [permission];
5207
+ for (const entry of requested) {
5208
+ if (entry.includes("*")) continue;
5209
+ if (CATALOG.has(entry) || warned.has(entry)) continue;
5210
+ warned.add(entry);
5211
+ console.warn(
5212
+ `[Can] Unknown permission "${entry}". It is not in the generated permission catalog. Check for a typo, or regenerate the catalog with \`pnpm generate-permissions\`.`
5213
+ );
5214
+ }
5215
+ }
5216
+ var FOCUS_TRAVERSAL_KEYS = /* @__PURE__ */ new Set(["Tab", "Escape"]);
5217
+ function blockInteraction(event) {
5218
+ event.preventDefault();
5219
+ event.stopPropagation();
5220
+ }
5221
+ function blockNonTraversalKey(event) {
5222
+ if (!FOCUS_TRAVERSAL_KEYS.has(event.key)) blockInteraction(event);
5223
+ }
5224
+ var warnedRenderPropMisuse = /* @__PURE__ */ new Set();
5225
+ function warnRenderPropVoidsProps(voided) {
5226
+ if (process.env.NODE_ENV === "production") return;
5227
+ if (voided.length === 0) return;
5228
+ const key = voided.join(",");
5229
+ if (warnedRenderPropMisuse.has(key)) return;
5230
+ warnedRenderPropMisuse.add(key);
5231
+ console.warn(
5232
+ `[Can] \`children\` is a function, so ${voided.map((prop) => `\`${prop}\``).join(", ")} ${voided.length === 1 ? "is" : "are"} ignored. A render prop owns every state: read \`allowed\` and \`status\` and render the disabled, loading and denied cases yourself, or pass an element instead of a function.`
5233
+ );
5234
+ }
5235
+ function disableElement(child) {
5236
+ return react.cloneElement(child, {
5237
+ "aria-disabled": "true",
5238
+ className: cn(child.props.className, "cursor-not-allowed opacity-50"),
5239
+ onClickCapture: blockInteraction,
5240
+ onKeyDownCapture: blockNonTraversalKey,
5241
+ onKeyUpCapture: blockNonTraversalKey,
5242
+ onPointerDownCapture: blockInteraction,
5243
+ onMouseDownCapture: blockInteraction
5244
+ });
5245
+ }
5246
+ function InteractionFirewall({ children }) {
5247
+ return /* @__PURE__ */ jsxRuntime.jsx(
5248
+ "span",
5249
+ {
5250
+ "data-slot": "can-blocked",
5251
+ className: "contents",
5252
+ onClickCapture: blockInteraction,
5253
+ onPointerDownCapture: blockInteraction,
5254
+ onMouseDownCapture: blockInteraction,
5255
+ onKeyDownCapture: blockNonTraversalKey,
5256
+ onKeyUpCapture: blockNonTraversalKey,
5257
+ children
5258
+ }
5259
+ );
5260
+ }
5261
+ function DisabledSubtree({
5262
+ children,
5263
+ className,
5264
+ ...props
5265
+ }) {
5266
+ const { "data-slot": _incomingDataSlot, ...restProps } = props;
5267
+ return /* @__PURE__ */ jsxRuntime.jsx(
5268
+ "span",
5269
+ {
5270
+ "data-slot": "can-disabled",
5271
+ "aria-disabled": "true",
5272
+ className: cn(
5273
+ "inline-flex cursor-not-allowed opacity-50",
5274
+ "*:pointer-events-none",
5275
+ className
5276
+ ),
5277
+ onClickCapture: blockInteraction,
5278
+ onPointerDownCapture: blockInteraction,
5279
+ onMouseDownCapture: blockInteraction,
5280
+ onKeyDownCapture: blockNonTraversalKey,
5281
+ onKeyUpCapture: blockNonTraversalKey,
5282
+ ...restProps,
5283
+ children
5284
+ }
5285
+ );
5286
+ }
5287
+ function Can({
5288
+ permission,
5289
+ mode = "any",
5290
+ negate = false,
5291
+ behavior = "hide",
5292
+ reason = null,
5293
+ fallback = null,
5294
+ loading,
5295
+ children
5296
+ }) {
5297
+ warnUnknownPermission(permission);
5298
+ const { can, status } = useAbility();
5299
+ const hasPermission = status === "ready" && can(permission, mode);
5192
5300
  const show = negate ? !hasPermission : hasPermission;
5193
5301
  if (typeof children === "function") {
5194
- return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: children(show) });
5302
+ warnRenderPropVoidsProps([
5303
+ ...behavior === "disable" ? ["behavior='disable'"] : [],
5304
+ ...reason !== null ? ["reason"] : [],
5305
+ ...fallback !== null ? ["fallback"] : [],
5306
+ ...loading !== void 0 ? ["loading"] : []
5307
+ ]);
5308
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: children({ allowed: show, status }) });
5195
5309
  }
5196
- return show ? /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children }) : /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: fallback });
5310
+ if (status === "loading" && loading !== void 0) {
5311
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: loading });
5312
+ }
5313
+ if (show) {
5314
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
5315
+ }
5316
+ if (behavior === "disable") {
5317
+ if (react.isValidElement(children) && children.type !== react.Fragment) {
5318
+ const disabledChild = disableElement(children);
5319
+ if (reason === null) {
5320
+ return /* @__PURE__ */ jsxRuntime.jsx(InteractionFirewall, { children: disabledChild });
5321
+ }
5322
+ return /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
5323
+ /* @__PURE__ */ jsxRuntime.jsx(InteractionFirewall, { children: /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: disabledChild }) }),
5324
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { children: reason })
5325
+ ] });
5326
+ }
5327
+ if (reason === null) {
5328
+ return /* @__PURE__ */ jsxRuntime.jsx(DisabledSubtree, { children });
5329
+ }
5330
+ return /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
5331
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(DisabledSubtree, { children }) }),
5332
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { children: reason })
5333
+ ] });
5334
+ }
5335
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: fallback });
5197
5336
  }
5198
5337
  Can.displayName = "Can";
5199
- function CanNot({ permission, mode = "any", fallback = null, children }) {
5200
- return /* @__PURE__ */ jsxRuntime.jsx(Can, { permission, mode, negate: true, fallback, children });
5338
+ function CanNot({
5339
+ permission,
5340
+ mode = "any",
5341
+ behavior = "hide",
5342
+ reason = null,
5343
+ fallback = null,
5344
+ loading,
5345
+ children
5346
+ }) {
5347
+ return /* @__PURE__ */ jsxRuntime.jsx(
5348
+ Can,
5349
+ {
5350
+ permission,
5351
+ mode,
5352
+ negate: true,
5353
+ behavior,
5354
+ reason,
5355
+ fallback,
5356
+ loading,
5357
+ children
5358
+ }
5359
+ );
5201
5360
  }
5202
5361
  CanNot.displayName = "CanNot";
5203
5362
  function useMediaQuery(query) {
@@ -9367,6 +9526,7 @@ exports.ItemHeader = ItemHeader;
9367
9526
  exports.ItemMedia = ItemMedia;
9368
9527
  exports.ItemSeparator = ItemSeparator;
9369
9528
  exports.ItemTitle = ItemTitle;
9529
+ exports.KNOWN_PERMISSIONS = KNOWN_PERMISSIONS;
9370
9530
  exports.Label = Label;
9371
9531
  exports.Link = Link;
9372
9532
  exports.Logo = Logo;
@@ -9527,6 +9687,7 @@ exports.toggleVariants = toggleVariants;
9527
9687
  exports.tooltipContentVariants = tooltipContentVariants;
9528
9688
  exports.transition = transition;
9529
9689
  exports.useAbility = useAbility;
9690
+ exports.useAbilityStatus = useAbilityStatus;
9530
9691
  exports.useAppForm = useAppForm;
9531
9692
  exports.useCan = useCan;
9532
9693
  exports.useCarousel = useCarousel;