@bizapps/ui 1.5.0 → 1.6.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
@@ -12,7 +12,7 @@ var dateFns = require('date-fns');
12
12
  var useEmblaCarousel = require('embla-carousel-react');
13
13
  var libphonenumberJs = require('libphonenumber-js');
14
14
  var cmdk = require('cmdk');
15
- var _3x2 = require('country-flag-icons/react/3x2');
15
+ var countryFlags = require('country-flag-icons/react/3x2');
16
16
  var react$1 = require('motion/react');
17
17
  var reactDropzone = require('react-dropzone');
18
18
  var Color = require('color');
@@ -30,7 +30,26 @@ var reactTable = require('@tanstack/react-table');
30
30
 
31
31
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
32
32
 
33
+ function _interopNamespace(e) {
34
+ if (e && e.__esModule) return e;
35
+ var n = Object.create(null);
36
+ if (e) {
37
+ Object.keys(e).forEach(function (k) {
38
+ if (k !== 'default') {
39
+ var d = Object.getOwnPropertyDescriptor(e, k);
40
+ Object.defineProperty(n, k, d.get ? d : {
41
+ enumerable: true,
42
+ get: function () { return e[k]; }
43
+ });
44
+ }
45
+ });
46
+ }
47
+ n.default = e;
48
+ return Object.freeze(n);
49
+ }
50
+
33
51
  var useEmblaCarousel__default = /*#__PURE__*/_interopDefault(useEmblaCarousel);
52
+ var countryFlags__namespace = /*#__PURE__*/_interopNamespace(countryFlags);
34
53
  var Color__default = /*#__PURE__*/_interopDefault(Color);
35
54
 
36
55
  // src/components/ui/Alert/alert.tsx
@@ -1054,6 +1073,15 @@ function Link({
1054
1073
  }
1055
1074
  );
1056
1075
  }
1076
+ function validatePhone(value) {
1077
+ if (!value) {
1078
+ return { isValid: false };
1079
+ }
1080
+ if (libphonenumberJs.isValidPhoneNumber(value)) {
1081
+ return { isValid: true };
1082
+ }
1083
+ return { isValid: false, problem: libphonenumberJs.validatePhoneNumberLength(value) ?? "INVALID" };
1084
+ }
1057
1085
  function Popover({ ...props }) {
1058
1086
  return /* @__PURE__ */ jsxRuntime.jsx(radixUi.Popover.Root, { "data-slot": "popover", ...props });
1059
1087
  }
@@ -1126,68 +1154,36 @@ function stripLeadingDialCode(raw, dialCode) {
1126
1154
  const code = dialCode.replace(/\D/g, "");
1127
1155
  return code && digits.startsWith(code) ? digits.length > code.length ? digits.slice(code.length) : "" : digits;
1128
1156
  }
1129
- var flagByCode = {
1130
- AR: _3x2.AR,
1131
- BO: _3x2.BO,
1132
- BR: _3x2.BR,
1133
- CA: _3x2.CA,
1134
- CL: _3x2.CL,
1135
- CO: _3x2.CO,
1136
- CR: _3x2.CR,
1137
- CU: _3x2.CU,
1138
- DE: _3x2.DE,
1139
- DO: _3x2.DO,
1140
- EC: _3x2.EC,
1141
- ES: _3x2.ES,
1142
- FR: _3x2.FR,
1143
- GB: _3x2.GB,
1144
- GT: _3x2.GT,
1145
- HN: _3x2.HN,
1146
- IN: _3x2.IN,
1147
- IT: _3x2.IT,
1148
- MX: _3x2.MX,
1149
- NI: _3x2.NI,
1150
- PA: _3x2.PA,
1151
- PE: _3x2.PE,
1152
- PT: _3x2.PT,
1153
- PY: _3x2.PY,
1154
- SV: _3x2.SV,
1155
- US: _3x2.US,
1156
- UY: _3x2.UY,
1157
- VE: _3x2.VE
1158
- };
1157
+ var flagByCode = countryFlags__namespace;
1159
1158
  function CountryFlag({
1160
1159
  code,
1161
1160
  flagUrl,
1162
1161
  className
1163
1162
  }) {
1164
- if (flagUrl) {
1165
- return /* @__PURE__ */ jsxRuntime.jsx(
1166
- "img",
1167
- {
1168
- src: flagUrl,
1169
- alt: "",
1170
- "aria-hidden": "true",
1171
- className: cn("size-4 shrink-0 rounded-[2px] object-cover", className)
1172
- }
1173
- );
1174
- }
1175
- const FlagComponent = flagByCode[(code || "").toUpperCase()];
1176
- if (FlagComponent) {
1177
- return /* @__PURE__ */ jsxRuntime.jsx(
1178
- FlagComponent,
1179
- {
1180
- "aria-hidden": "true",
1181
- className: cn("size-4 shrink-0 rounded-[2px]", className)
1182
- }
1183
- );
1184
- }
1185
- return /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", className: cn("bg-muted size-4 shrink-0 rounded-full", className) });
1163
+ const isoCode = (code || "").toUpperCase();
1164
+ const FlagComponent = flagByCode[isoCode];
1165
+ const flag = flagUrl ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: flagUrl, alt: "", "aria-hidden": "true", className: "size-full object-cover" }) : FlagComponent ? /* @__PURE__ */ jsxRuntime.jsx(FlagComponent, { "aria-hidden": "true", className: "size-full" }) : null;
1166
+ return /* @__PURE__ */ jsxRuntime.jsx(
1167
+ "span",
1168
+ {
1169
+ "data-slot": "phone-field-country-flag",
1170
+ "data-country": isoCode || void 0,
1171
+ "data-fallback": flag ? void 0 : "true",
1172
+ "aria-hidden": "true",
1173
+ className: cn(
1174
+ "size-4 shrink-0 overflow-hidden rounded-[2px]",
1175
+ !flag && "bg-muted rounded-full",
1176
+ className
1177
+ ),
1178
+ children: flag
1179
+ }
1180
+ );
1186
1181
  }
1187
1182
  function PhoneField({
1188
1183
  countries,
1189
1184
  value,
1190
1185
  onValueChange,
1186
+ onValidityChange,
1191
1187
  defaultCountry,
1192
1188
  placeholder = "Phone number",
1193
1189
  disabled = false,
@@ -1204,6 +1200,7 @@ function PhoneField({
1204
1200
  const listRef = react.useRef(null);
1205
1201
  const inputRef = react.useRef(null);
1206
1202
  const caretRef = react.useRef(null);
1203
+ const lastValidityRef = react.useRef(null);
1207
1204
  const listId = `${react.useId()}-countries-list`;
1208
1205
  const isControlled = value !== void 0;
1209
1206
  const currentValue = isControlled ? value : internalValue;
@@ -1214,7 +1211,9 @@ function PhoneField({
1214
1211
  const callingCodeInList = parsedCallingCode !== void 0 && countries.some(
1215
1212
  (country) => country.dialCode.replace(/\D/g, "") === parsedCallingCode
1216
1213
  );
1217
- const representedCode = countryInList ? parsedCountry : callingCodeInList ? countries.find(
1214
+ const pickedCountry = pickedCode ? countries.find((country) => country.code.toUpperCase() === pickedCode.toUpperCase()) : void 0;
1215
+ const pickMatchesValue = pickedCountry !== void 0 && pickedCountry.dialCode.replace(/\D/g, "") === parsedCallingCode;
1216
+ const representedCode = countryInList ? parsedCountry : pickMatchesValue ? pickedCountry.code : callingCodeInList ? countries.find(
1218
1217
  (country) => country.dialCode.replace(/\D/g, "") === parsedCallingCode
1219
1218
  )?.code : void 0;
1220
1219
  const selectedCode = representedCode ?? pickedCode ?? defaultCountry ?? countries[0]?.code;
@@ -1229,6 +1228,15 @@ function PhoneField({
1229
1228
  nationalDigits
1230
1229
  ) : nationalDigits;
1231
1230
  const isInvalid = inputProps["aria-invalid"] === true || inputProps["aria-invalid"] === "true";
1231
+ const { isValid, problem } = validatePhone(currentValue);
1232
+ react.useEffect(() => {
1233
+ const last = lastValidityRef.current;
1234
+ if (last && last.isValid === isValid && last.problem === problem) {
1235
+ return;
1236
+ }
1237
+ lastValidityRef.current = { isValid, problem };
1238
+ onValidityChange?.({ isValid, problem });
1239
+ }, [isValid, problem, onValidityChange]);
1232
1240
  react.useLayoutEffect(() => {
1233
1241
  const input = inputRef.current;
1234
1242
  const caret = caretRef.current;
@@ -1321,17 +1329,21 @@ function PhoneField({
1321
1329
  }
1322
1330
  }
1323
1331
  }
1324
- if (nextPickedCode) {
1325
- setPickedCode(nextPickedCode);
1326
- }
1327
- if (!national) {
1328
- onValueChange?.("");
1329
- if (!isControlled) {
1330
- setInternalValue("");
1332
+ const next = national ? `+${emitCode}${national}` : "";
1333
+ const grew = national.replace(/\D/g, "").length > nationalDigits.length;
1334
+ const isPaste = nativeEvent?.inputType === "insertFromPaste";
1335
+ if (grew && !isPaste && libphonenumberJs.validatePhoneNumberLength(next) === "TOO_LONG") {
1336
+ if (input) {
1337
+ const caret = Math.max(0, (input.selectionStart ?? inputValue.length) - 1);
1338
+ input.value = inputValue;
1339
+ input.setSelectionRange(caret, caret);
1331
1340
  }
1341
+ caretRef.current = null;
1332
1342
  return;
1333
1343
  }
1334
- const next = `+${emitCode}${national}`;
1344
+ if (nextPickedCode) {
1345
+ setPickedCode(nextPickedCode);
1346
+ }
1335
1347
  onValueChange?.(next);
1336
1348
  if (!isControlled) {
1337
1349
  setInternalValue(next);
@@ -5122,6 +5134,8 @@ function NavigationMenuIndicator({
5122
5134
  }
5123
5135
  );
5124
5136
  }
5137
+
5138
+ // src/components/authorization/policy.ts
5125
5139
  function matchPermission(pattern, permission) {
5126
5140
  if (pattern === "*") return true;
5127
5141
  if (pattern === permission) return true;
@@ -5137,6 +5151,15 @@ function matchesAny(permissionSet, permission) {
5137
5151
  }
5138
5152
  return false;
5139
5153
  }
5154
+ function can(permissionSet, perms, mode = "any") {
5155
+ const list = Array.isArray(perms) ? perms : [perms];
5156
+ if (list.length === 0) return false;
5157
+ if (permissionSet.has("*")) return true;
5158
+ if (mode === "all") {
5159
+ return list.every((p) => matchesAny(permissionSet, p));
5160
+ }
5161
+ return list.some((p) => matchesAny(permissionSet, p));
5162
+ }
5140
5163
  var AbilityContext = react.createContext(void 0);
5141
5164
  AbilityContext.displayName = "AbilityContext";
5142
5165
  function AbilityProvider({ children, permissions }) {
@@ -5145,16 +5168,8 @@ function AbilityProvider({ children, permissions }) {
5145
5168
  );
5146
5169
  const [imperativelyResolved, setImperativelyResolved] = react.useState(false);
5147
5170
  const status = permissions !== void 0 || imperativelyResolved ? "ready" : "loading";
5148
- const can = react.useCallback(
5149
- (perms, mode = "any") => {
5150
- const list = Array.isArray(perms) ? perms : [perms];
5151
- if (list.length === 0) return false;
5152
- if (permissionSet.has("*")) return true;
5153
- if (mode === "all") {
5154
- return list.every((p) => matchesAny(permissionSet, p));
5155
- }
5156
- return list.some((p) => matchesAny(permissionSet, p));
5157
- },
5171
+ const can2 = react.useCallback(
5172
+ (perms, mode = "any") => can(permissionSet, perms, mode),
5158
5173
  [permissionSet]
5159
5174
  );
5160
5175
  const setAbilities = react.useCallback((perms) => {
@@ -5174,8 +5189,8 @@ function AbilityProvider({ children, permissions }) {
5174
5189
  setPermissionSet(new Set(permissions));
5175
5190
  }, [permissionKey, permissions]);
5176
5191
  const value = react.useMemo(
5177
- () => ({ can, setAbilities, clearAbilities, status }),
5178
- [can, setAbilities, clearAbilities, status]
5192
+ () => ({ can: can2, setAbilities, clearAbilities, status }),
5193
+ [can2, setAbilities, clearAbilities, status]
5179
5194
  );
5180
5195
  return /* @__PURE__ */ jsxRuntime.jsx(AbilityContext.Provider, { value, children });
5181
5196
  }
@@ -5187,8 +5202,8 @@ function useAbility() {
5187
5202
  return context;
5188
5203
  }
5189
5204
  function useCan(permissions, mode = "any") {
5190
- const { can } = useAbility();
5191
- return can(permissions, mode);
5205
+ const { can: can2 } = useAbility();
5206
+ return can2(permissions, mode);
5192
5207
  }
5193
5208
  function useAbilityStatus() {
5194
5209
  return useAbility().status;
@@ -5295,8 +5310,8 @@ function Can({
5295
5310
  children
5296
5311
  }) {
5297
5312
  warnUnknownPermission(permission);
5298
- const { can, status } = useAbility();
5299
- const hasPermission = status === "ready" && can(permission, mode);
5313
+ const { can: can2, status } = useAbility();
5314
+ const hasPermission = status === "ready" && can2(permission, mode);
5300
5315
  const show = negate ? !hasPermission : hasPermission;
5301
5316
  if (typeof children === "function") {
5302
5317
  warnRenderPropVoidsProps([
@@ -9702,5 +9717,6 @@ exports.useTableSizing = useTableSizing;
9702
9717
  exports.useTableSorting = useTableSorting;
9703
9718
  exports.useTableVisibility = useTableVisibility;
9704
9719
  exports.useToast = useToast;
9720
+ exports.validatePhone = validatePhone;
9705
9721
  //# sourceMappingURL=main.cjs.map
9706
9722
  //# sourceMappingURL=main.cjs.map