@chekinapp/ui 0.0.139 → 0.0.141

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/index.js CHANGED
@@ -13162,6 +13162,7 @@ function useSelectState(params) {
13162
13162
  onKeyDown,
13163
13163
  onFocus,
13164
13164
  onBlur,
13165
+ inputValue: controlledInputValue,
13165
13166
  onInputChange,
13166
13167
  isSearchInDropdown,
13167
13168
  searchable = true
@@ -13179,9 +13180,17 @@ function useSelectState(params) {
13179
13180
  [singleSelected, getValueLabel]
13180
13181
  );
13181
13182
  const isSearchOnlyInput = searchable && (isMulti || Boolean(isSearchInDropdown));
13182
- const [inputValue, setInputValue] = React48.useState(
13183
+ const isInputControlled = controlledInputValue !== void 0;
13184
+ const [internalInputValue, setInternalInputValue] = React48.useState(
13183
13185
  searchable && !isSearchOnlyInput ? valueLabel : ""
13184
13186
  );
13187
+ const inputValue = isInputControlled ? controlledInputValue : internalInputValue;
13188
+ const setInputValue = React48.useCallback(
13189
+ (next) => {
13190
+ if (!isInputControlled) setInternalInputValue(next);
13191
+ },
13192
+ [isInputControlled]
13193
+ );
13185
13194
  const hasValue = selectedOptions.length > 0;
13186
13195
  const isBlocked = Boolean(disabled) || Boolean(loading) || Boolean(readOnly);
13187
13196
  const hasInvalidState = Boolean(error);
@@ -13348,7 +13357,7 @@ function useSelectState(params) {
13348
13357
  onInputChange?.(nextValue);
13349
13358
  if (!isOpen) setIsOpen(true);
13350
13359
  },
13351
- [isOpen, onInputChange, searchable, setIsOpen]
13360
+ [isOpen, onInputChange, searchable, setIsOpen, setInputValue]
13352
13361
  );
13353
13362
  const handleInputFocus = React48.useCallback(
13354
13363
  (event) => {
@@ -13876,6 +13885,7 @@ function SelectInternal(props, ref) {
13876
13885
  hideIndicator,
13877
13886
  openMenuOnFocus,
13878
13887
  components: userComponents,
13888
+ inputValue,
13879
13889
  onInputChange,
13880
13890
  searchable = true,
13881
13891
  searchPosition = "trigger",
@@ -13945,6 +13955,7 @@ function SelectInternal(props, ref) {
13945
13955
  onKeyDown,
13946
13956
  onFocus,
13947
13957
  onBlur,
13958
+ inputValue,
13948
13959
  onInputChange,
13949
13960
  isSearchInDropdown,
13950
13961
  searchable
@@ -14125,6 +14136,30 @@ var Select = React49.forwardRef(SelectInternal);
14125
14136
 
14126
14137
  // src/dashboard/phone-input/utils.ts
14127
14138
  var PREFIX_REGEX = /^\+/;
14139
+ function isPhoneInputValue(value) {
14140
+ if (typeof value === "string" || typeof value === "number") {
14141
+ return false;
14142
+ }
14143
+ return Boolean(value && ("code" in value || "number" in value));
14144
+ }
14145
+ function getPhoneValuePart(value) {
14146
+ if (typeof value === "string" || typeof value === "number") {
14147
+ return String(value);
14148
+ }
14149
+ return void 0;
14150
+ }
14151
+ function toPhoneValue(value, fallbackCode, fallbackNumber) {
14152
+ if (value === null || value === void 0) {
14153
+ return { code: fallbackCode ?? "", number: fallbackNumber ?? "" };
14154
+ }
14155
+ if (isPhoneInputValue(value)) {
14156
+ return {
14157
+ code: getPhoneValuePart(value.code) ?? fallbackCode ?? "",
14158
+ number: getPhoneValuePart(value.number) ?? fallbackNumber ?? ""
14159
+ };
14160
+ }
14161
+ return { code: fallbackCode ?? "", number: fallbackNumber ?? String(value) };
14162
+ }
14128
14163
  function clearPhoneNumber(value) {
14129
14164
  return value.replace(/[^0-9]/g, "");
14130
14165
  }
@@ -14168,190 +14203,228 @@ function formatPhoneCodeOptionLabel(option) {
14168
14203
 
14169
14204
  // src/dashboard/phone-input/PhoneInput.tsx
14170
14205
  import { jsx as jsx156, jsxs as jsxs100 } from "react/jsx-runtime";
14171
- var EMPTY_VALUE = { code: "", number: "" };
14172
- var PhoneInput = React50.forwardRef(function PhoneInput2({
14173
- options,
14174
- value,
14175
- onChange,
14176
- onFocus,
14177
- onBlur,
14178
- name,
14179
- codeName,
14180
- numberName,
14181
- label,
14182
- topLabel,
14183
- prefixLabel,
14184
- placeholder,
14185
- codePlaceholder = "+00",
14186
- disabled,
14187
- loading,
14188
- readOnly,
14189
- codeReadOnly,
14190
- optional,
14191
- tooltip,
14192
- error,
14193
- invalid,
14194
- className,
14195
- autoDetectCode = true,
14196
- searchable = true,
14197
- defaultCode
14198
- }, ref) {
14199
- const { t } = useTranslation33();
14200
- const groupLabelId = React50.useId();
14201
- const errorMsgId = React50.useId();
14202
- const numberInputRef = React50.useRef(null);
14203
- const safeValue = value ?? EMPTY_VALUE;
14204
- const effectiveCode = safeValue.code || defaultCode || "";
14205
- const resolvedLabel = label ?? "";
14206
- const hasExternalError = Boolean(error);
14207
- const isPrefixRequired = autoDetectCode && Boolean(safeValue.number) && !effectiveCode;
14208
- const hasInvalidState = hasExternalError || Boolean(invalid) || isPrefixRequired;
14209
- const errorMessage = error ?? (isPrefixRequired ? t("prefix_required") : void 0);
14210
- const combinedValue = effectiveCode || safeValue.number ? `${effectiveCode}${safeValue.number}` : "";
14211
- const codeOptions = React50.useMemo(
14212
- () => options.map((option) => ({
14213
- value: option.value,
14214
- label: formatPhoneCodeOptionLabel(option),
14215
- data: option.data,
14216
- isDisabled: option.disabled
14217
- })),
14218
- [options]
14219
- );
14220
- const selectedCodeOption = React50.useMemo(
14221
- () => codeOptions.find((option) => option.value === effectiveCode) ?? null,
14222
- [codeOptions, effectiveCode]
14223
- );
14224
- const parsePhoneValue = React50.useMemo(
14225
- () => parsePhoneValueWithOptions(options),
14226
- [options]
14227
- );
14228
- const emitChange = (next) => {
14229
- onChange?.(next, name);
14230
- };
14231
- const handleCodeChange = (option) => {
14232
- if (!option) return;
14233
- emitChange({ code: option.value, number: safeValue.number });
14234
- if (!disabled && !readOnly) {
14235
- setTimeout(() => numberInputRef.current?.focus(), 0);
14236
- }
14237
- };
14238
- const handleNumberChange = (event) => {
14239
- if (readOnly || disabled) return;
14240
- const rawValue = event.target.value;
14241
- if (!autoDetectCode) {
14242
- emitChange({ code: effectiveCode, number: clearPhoneNumber(rawValue) });
14243
- return;
14244
- }
14245
- const parsed = parsePhoneValue(rawValue);
14246
- const cleanedNumber = clearPhoneNumber(parsed.number);
14247
- if (parsed.code) {
14248
- emitChange({ code: parsed.code, number: cleanedNumber });
14249
- return;
14250
- }
14251
- emitChange({ code: effectiveCode, number: cleanedNumber });
14252
- };
14253
- return /* @__PURE__ */ jsxs100(
14254
- "div",
14255
- {
14256
- className: cn(
14257
- "relative w-[var(--field-width,100%)] max-w-[var(--field-max-width,296px)]",
14258
- disabled && "cursor-not-allowed opacity-50",
14259
- loading && "cursor-progress",
14260
- className
14261
- ),
14262
- children: [
14263
- name && /* @__PURE__ */ jsx156("input", { type: "hidden", name, value: combinedValue, disabled }),
14264
- codeName && /* @__PURE__ */ jsx156("input", { type: "hidden", name: codeName, value: effectiveCode, disabled }),
14265
- numberName && /* @__PURE__ */ jsx156(
14266
- "input",
14267
- {
14268
- type: "hidden",
14269
- name: numberName,
14270
- value: safeValue.number,
14271
- disabled
14272
- }
14273
- ),
14274
- topLabel && /* @__PURE__ */ jsx156(
14275
- "span",
14276
- {
14277
- id: groupLabelId,
14278
- className: "mb-2 block text-[14px] font-medium text-[var(--chekin-color-brand-navy)]",
14279
- children: topLabel
14280
- }
14281
- ),
14282
- /* @__PURE__ */ jsxs100(
14283
- "div",
14284
- {
14285
- role: "group",
14286
- "aria-labelledby": topLabel ? groupLabelId : void 0,
14287
- className: "grid grid-cols-[96px_minmax(0,1fr)] gap-2",
14288
- children: [
14289
- /* @__PURE__ */ jsx156(
14290
- Select,
14291
- {
14292
- ref,
14293
- options: codeOptions,
14294
- value: selectedCodeOption,
14295
- onChange: handleCodeChange,
14296
- label: prefixLabel,
14297
- placeholder: codePlaceholder,
14298
- disabled,
14299
- readOnly: Boolean(readOnly) || Boolean(codeReadOnly),
14300
- loading,
14301
- invalid: hasInvalidState,
14302
- hideErrorMessage: true,
14303
- searchPosition: searchable ? "dropdown" : "trigger",
14304
- searchable,
14305
- filterOption: countriesFilter,
14306
- clearable: false,
14307
- getValueLabel: (option) => option.value,
14308
- className: "max-w-none w-auto",
14309
- dropdownClassName: "right-auto w-[280px]"
14310
- }
14311
- ),
14312
- /* @__PURE__ */ jsx156(
14313
- Input,
14314
- {
14315
- ref: numberInputRef,
14316
- type: "tel",
14317
- inputMode: "tel",
14318
- autoComplete: "tel-national",
14319
- label: resolvedLabel,
14320
- value: safeValue.number,
14321
- placeholder,
14322
- disabled,
14323
- readOnly,
14324
- loading,
14325
- invalid: hasInvalidState,
14326
- tooltip,
14327
- "aria-label": resolvedLabel || name,
14328
- "aria-describedby": errorMessage ? errorMsgId : void 0,
14329
- onChange: handleNumberChange,
14330
- onFocus,
14331
- onBlur,
14332
- renderErrorMessage: false,
14333
- wrapperClassName: "max-w-none w-auto",
14334
- contentClassName: readOnly ? "!cursor-default" : void 0,
14335
- inputClassName: readOnly ? "!cursor-default" : void 0
14336
- }
14337
- )
14338
- ]
14339
- }
14206
+ var PhoneInput = React50.forwardRef(
14207
+ function PhoneInput2({
14208
+ options,
14209
+ value,
14210
+ onChange,
14211
+ onFocus,
14212
+ onBlur,
14213
+ name,
14214
+ codeName,
14215
+ numberName,
14216
+ label,
14217
+ topLabel,
14218
+ prefixLabel,
14219
+ placeholder,
14220
+ codePlaceholder = "+00",
14221
+ disabled,
14222
+ loading,
14223
+ readOnly,
14224
+ codeReadOnly,
14225
+ optional,
14226
+ tooltip,
14227
+ error,
14228
+ invalid,
14229
+ className,
14230
+ autoDetectCode = true,
14231
+ searchable = true,
14232
+ defaultCode
14233
+ }, ref) {
14234
+ const { t } = useTranslation33();
14235
+ const groupLabelId = React50.useId();
14236
+ const errorMsgId = React50.useId();
14237
+ const numberInputRef = React50.useRef(null);
14238
+ const [codeSearchValue, setCodeSearchValue] = React50.useState("");
14239
+ const safeValue = toPhoneValue(value);
14240
+ const effectiveCode = safeValue.code || defaultCode || "";
14241
+ const resolvedLabel = label ?? "";
14242
+ const hasExternalError = Boolean(error);
14243
+ const isPrefixRequired = autoDetectCode && Boolean(safeValue.number) && !effectiveCode;
14244
+ const hasInvalidState = hasExternalError || Boolean(invalid) || isPrefixRequired;
14245
+ const errorMessage = error ?? (isPrefixRequired ? t("prefix_required") : void 0);
14246
+ const combinedValue = effectiveCode || safeValue.number ? `${effectiveCode}${safeValue.number}` : "";
14247
+ const codeOptions = React50.useMemo(
14248
+ () => options.map((option) => ({
14249
+ value: option.value,
14250
+ label: formatPhoneCodeOptionLabel(option),
14251
+ data: option.data,
14252
+ isDisabled: option.disabled
14253
+ })),
14254
+ [options]
14255
+ );
14256
+ const selectedCodeOption = React50.useMemo(
14257
+ () => codeOptions.find((option) => option.value === effectiveCode) ?? null,
14258
+ [codeOptions, effectiveCode]
14259
+ );
14260
+ const parsePhoneValue = React50.useMemo(
14261
+ () => parsePhoneValueWithOptions(options),
14262
+ [options]
14263
+ );
14264
+ const emitChange = (next) => {
14265
+ onChange?.(next, name);
14266
+ };
14267
+ const handleCodeChange = (option) => {
14268
+ if (!option) return;
14269
+ emitChange({ code: option.value, number: safeValue.number });
14270
+ if (!disabled && !readOnly) {
14271
+ setTimeout(() => numberInputRef.current?.focus(), 0);
14272
+ }
14273
+ };
14274
+ const handleNumberChange = (event) => {
14275
+ if (readOnly || disabled) return;
14276
+ const rawValue = event.target.value;
14277
+ if (!autoDetectCode) {
14278
+ emitChange({ code: effectiveCode, number: clearPhoneNumber(rawValue) });
14279
+ return;
14280
+ }
14281
+ const parsed = parsePhoneValue(rawValue);
14282
+ const cleanedNumber = clearPhoneNumber(parsed.number);
14283
+ if (parsed.code) {
14284
+ emitChange({ code: parsed.code, number: cleanedNumber });
14285
+ return;
14286
+ }
14287
+ emitChange({ code: effectiveCode, number: cleanedNumber });
14288
+ };
14289
+ const effectiveCodeRef = React50.useRef(effectiveCode);
14290
+ const numberValueRef = React50.useRef(safeValue.number);
14291
+ const codeSearchValueRef = React50.useRef(codeSearchValue);
14292
+ const onChangeRef = React50.useRef(onChange);
14293
+ const nameRef = React50.useRef(name);
14294
+ effectiveCodeRef.current = effectiveCode;
14295
+ numberValueRef.current = safeValue.number;
14296
+ codeSearchValueRef.current = codeSearchValue;
14297
+ onChangeRef.current = onChange;
14298
+ nameRef.current = name;
14299
+ React50.useImperativeHandle(
14300
+ ref,
14301
+ () => ({
14302
+ getCodeSearchValue: () => codeSearchValueRef.current,
14303
+ setCodeSearchValue: (next) => setCodeSearchValue(next),
14304
+ getNumberValue: () => numberValueRef.current,
14305
+ setNumberValue: (next) => {
14306
+ const cleanedNumber = clearPhoneNumber(next);
14307
+ onChangeRef.current?.(
14308
+ { code: effectiveCodeRef.current, number: cleanedNumber },
14309
+ nameRef.current
14310
+ );
14311
+ },
14312
+ focus: () => numberInputRef.current?.focus()
14313
+ }),
14314
+ []
14315
+ );
14316
+ return /* @__PURE__ */ jsxs100(
14317
+ "div",
14318
+ {
14319
+ className: cn(
14320
+ "relative w-[var(--field-width,100%)] max-w-[var(--field-max-width,296px)]",
14321
+ disabled && "cursor-not-allowed opacity-50",
14322
+ loading && "cursor-progress",
14323
+ className
14340
14324
  ),
14341
- !errorMessage && optional && /* @__PURE__ */ jsx156("span", { className: "mt-[1px] block text-left text-[14px] font-medium text-[var(--chekin-color-gray-1)]", children: typeof optional === "string" ? optional : t("optional") }),
14342
- errorMessage && /* @__PURE__ */ jsx156(
14343
- FieldErrorMessage,
14344
- {
14345
- id: errorMsgId,
14346
- message: errorMessage,
14347
- "data-testid": name ? `${name}-error` : void 0,
14348
- className: "mt-[1px] text-[14px]"
14349
- }
14350
- )
14351
- ]
14352
- }
14353
- );
14354
- });
14325
+ children: [
14326
+ name && /* @__PURE__ */ jsx156("input", { type: "hidden", name, value: combinedValue, disabled }),
14327
+ codeName && /* @__PURE__ */ jsx156(
14328
+ "input",
14329
+ {
14330
+ type: "hidden",
14331
+ name: codeName,
14332
+ value: effectiveCode,
14333
+ disabled
14334
+ }
14335
+ ),
14336
+ numberName && /* @__PURE__ */ jsx156(
14337
+ "input",
14338
+ {
14339
+ type: "hidden",
14340
+ name: numberName,
14341
+ value: safeValue.number,
14342
+ disabled
14343
+ }
14344
+ ),
14345
+ topLabel && /* @__PURE__ */ jsx156(
14346
+ "span",
14347
+ {
14348
+ id: groupLabelId,
14349
+ className: "mb-2 block text-[14px] font-medium text-[var(--chekin-color-brand-navy)]",
14350
+ children: topLabel
14351
+ }
14352
+ ),
14353
+ /* @__PURE__ */ jsxs100(
14354
+ "div",
14355
+ {
14356
+ role: "group",
14357
+ "aria-labelledby": topLabel ? groupLabelId : void 0,
14358
+ className: "grid grid-cols-[96px_minmax(0,1fr)] gap-2",
14359
+ children: [
14360
+ /* @__PURE__ */ jsx156(
14361
+ Select,
14362
+ {
14363
+ options: codeOptions,
14364
+ value: selectedCodeOption,
14365
+ onChange: handleCodeChange,
14366
+ label: prefixLabel,
14367
+ placeholder: codePlaceholder,
14368
+ disabled,
14369
+ readOnly: Boolean(readOnly) || Boolean(codeReadOnly),
14370
+ loading,
14371
+ invalid: hasInvalidState,
14372
+ hideErrorMessage: true,
14373
+ searchPosition: searchable ? "dropdown" : "trigger",
14374
+ searchable,
14375
+ filterOption: countriesFilter,
14376
+ clearable: false,
14377
+ getValueLabel: (option) => option.value,
14378
+ className: "max-w-none w-auto",
14379
+ dropdownClassName: "right-auto w-[280px]",
14380
+ inputValue: searchable ? codeSearchValue : void 0,
14381
+ onInputChange: setCodeSearchValue
14382
+ }
14383
+ ),
14384
+ /* @__PURE__ */ jsx156(
14385
+ Input,
14386
+ {
14387
+ ref: numberInputRef,
14388
+ type: "tel",
14389
+ inputMode: "tel",
14390
+ autoComplete: "tel-national",
14391
+ label: resolvedLabel,
14392
+ value: safeValue.number,
14393
+ placeholder,
14394
+ disabled,
14395
+ readOnly,
14396
+ loading,
14397
+ invalid: hasInvalidState,
14398
+ tooltip,
14399
+ "aria-label": resolvedLabel || name,
14400
+ "aria-describedby": errorMessage ? errorMsgId : void 0,
14401
+ onChange: handleNumberChange,
14402
+ onFocus,
14403
+ onBlur,
14404
+ renderErrorMessage: false,
14405
+ wrapperClassName: "max-w-none w-auto",
14406
+ contentClassName: readOnly ? "!cursor-default" : void 0,
14407
+ inputClassName: readOnly ? "!cursor-default" : void 0
14408
+ }
14409
+ )
14410
+ ]
14411
+ }
14412
+ ),
14413
+ !errorMessage && optional && /* @__PURE__ */ jsx156("span", { className: "mt-[1px] block text-left text-[14px] font-medium text-[var(--chekin-color-gray-1)]", children: typeof optional === "string" ? optional : t("optional") }),
14414
+ errorMessage && /* @__PURE__ */ jsx156(
14415
+ FieldErrorMessage,
14416
+ {
14417
+ id: errorMsgId,
14418
+ message: errorMessage,
14419
+ "data-testid": name ? `${name}-error` : void 0,
14420
+ className: "mt-[1px] text-[14px]"
14421
+ }
14422
+ )
14423
+ ]
14424
+ }
14425
+ );
14426
+ }
14427
+ );
14355
14428
  PhoneInput.displayName = "PhoneInput";
14356
14429
 
14357
14430
  // src/dashboard/creatable-select/CreatableSelect.tsx