@elcrm/form 0.1.1 → 0.1.3

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 (104) hide show
  1. package/README.md +162 -203
  2. package/dist/assets/styles/Check.module.css +1 -0
  3. package/dist/assets/styles/Code.module.css +1 -0
  4. package/dist/assets/styles/Color.module.css +1 -1
  5. package/dist/assets/styles/Drag.module.css +1 -0
  6. package/dist/assets/styles/Field.module.css +1 -1
  7. package/dist/assets/styles/FieldGroup.module.css +1 -0
  8. package/dist/assets/styles/File.module.css +1 -0
  9. package/dist/assets/styles/Form.module.css +1 -1
  10. package/dist/assets/styles/Radio.module.css +1 -0
  11. package/dist/assets/styles/Rating.module.css +1 -0
  12. package/dist/assets/styles/Rich.module.css +1 -0
  13. package/dist/assets/styles/Select.module.css +1 -1
  14. package/dist/assets/styles/Tabs.module.css +1 -0
  15. package/dist/assets/styles/Tags.module.css +1 -0
  16. package/dist/assets/styles/Time.module.css +1 -0
  17. package/dist/core/Field.d.ts +26 -10
  18. package/dist/core/Field.js +2 -2
  19. package/dist/dark.css +38 -11
  20. package/dist/fields/Card.d.ts +12 -0
  21. package/dist/fields/Card.js +1 -0
  22. package/dist/fields/Check.d.ts +6 -2
  23. package/dist/fields/Check.js +1 -1
  24. package/dist/fields/Code.d.ts +13 -4
  25. package/dist/fields/Code.js +1 -1
  26. package/dist/fields/Color.d.ts +8 -13
  27. package/dist/fields/Color.js +1 -1
  28. package/dist/fields/ColorPanel.d.ts +16 -0
  29. package/dist/fields/ColorPanel.js +1 -0
  30. package/dist/fields/Date.d.ts +3 -1
  31. package/dist/fields/Date.js +1 -1
  32. package/dist/fields/DateCalendar.d.ts +16 -0
  33. package/dist/fields/DateCalendar.js +1 -0
  34. package/dist/fields/Display.d.ts +8 -5
  35. package/dist/fields/Display.js +2 -1
  36. package/dist/fields/DragDrop.d.ts +13 -3
  37. package/dist/fields/DragDrop.js +1 -1
  38. package/dist/fields/Email.d.ts +6 -3
  39. package/dist/fields/Email.js +1 -1
  40. package/dist/fields/FieldGroup.d.ts +107 -0
  41. package/dist/fields/FieldGroup.js +1 -0
  42. package/dist/fields/File.js +1 -1
  43. package/dist/fields/Hidden.js +1 -1
  44. package/dist/fields/Input.js +1 -1
  45. package/dist/fields/Mask.d.ts +2 -1
  46. package/dist/fields/Mask.js +1 -1
  47. package/dist/fields/Modal.js +1 -1
  48. package/dist/fields/Money.d.ts +2 -1
  49. package/dist/fields/Money.js +1 -1
  50. package/dist/fields/NativeTextField.js +1 -1
  51. package/dist/fields/Numeric.d.ts +2 -1
  52. package/dist/fields/Numeric.js +1 -1
  53. package/dist/fields/Options.js +1 -1
  54. package/dist/fields/Password.js +1 -1
  55. package/dist/fields/Percent.js +1 -1
  56. package/dist/fields/Phone.js +1 -1
  57. package/dist/fields/Radio.d.ts +3 -1
  58. package/dist/fields/Radio.js +1 -1
  59. package/dist/fields/Range.d.ts +9 -6
  60. package/dist/fields/Range.js +1 -1
  61. package/dist/fields/Rating.js +1 -1
  62. package/dist/fields/RichText.js +1 -1
  63. package/dist/fields/Select.js +1 -1
  64. package/dist/fields/Tabs.d.ts +30 -0
  65. package/dist/fields/Tabs.js +1 -0
  66. package/dist/fields/Tags.js +1 -1
  67. package/dist/fields/Textarea.js +1 -1
  68. package/dist/fields/Time.js +1 -1
  69. package/dist/fields/TimePicker.d.ts +15 -0
  70. package/dist/fields/TimePicker.js +1 -0
  71. package/dist/fields/cardUtils.d.ts +37 -0
  72. package/dist/fields/cardUtils.js +1 -0
  73. package/dist/fields/colorUtils.d.ts +29 -0
  74. package/dist/fields/colorUtils.js +1 -0
  75. package/dist/fields/dateUtils.d.ts +32 -0
  76. package/dist/fields/dateUtils.js +1 -0
  77. package/dist/fields/emailUtils.d.ts +4 -0
  78. package/dist/fields/emailUtils.js +1 -0
  79. package/dist/fields/timeUtils.d.ts +23 -0
  80. package/dist/fields/timeUtils.js +1 -0
  81. package/dist/fields/type.d.ts +4 -3
  82. package/dist/hooks/use.d.ts +12 -7
  83. package/dist/index.d.ts +19 -9
  84. package/dist/index.js +2 -2
  85. package/dist/index.umd.js +3 -2
  86. package/dist/light.css +39 -12
  87. package/dist/package.js +1 -1
  88. package/dist/style.css +26 -4
  89. package/dist/styles/Check.module.js +1 -0
  90. package/dist/styles/Code.module.js +1 -0
  91. package/dist/styles/Color.module.js +1 -1
  92. package/dist/styles/Drag.module.js +1 -0
  93. package/dist/styles/Field.module.js +1 -1
  94. package/dist/styles/FieldGroup.module.js +1 -0
  95. package/dist/styles/File.module.js +1 -0
  96. package/dist/styles/Form.module.js +1 -1
  97. package/dist/styles/Radio.module.js +1 -0
  98. package/dist/styles/Rating.module.js +1 -0
  99. package/dist/styles/Rich.module.js +1 -0
  100. package/dist/styles/Select.module.js +1 -1
  101. package/dist/styles/Tabs.module.js +1 -0
  102. package/dist/styles/Tags.module.js +1 -0
  103. package/dist/styles/Time.module.js +1 -0
  104. package/package.json +5 -5
@@ -1 +1 @@
1
- import e from"../styles/Field.module.js";import t,{useFieldA11y as n}from"../core/Field.js";import{useFormFieldState as r}from"../hooks/use.js";import i,{asEditableClipboard as a}from"../events/onEvent.js";import{isEmptyTextLike as o}from"./visibility.js";import{PHONE_MASK_DEFAULTS as s}from"../mask/phoneDefaults.js";import{useFormInit as c}from"../FormInitContext.js";import l from"react";import{jsx as u,jsxs as d}from"react/jsx-runtime";var f={...s},p=!1,m=null;function h(){return p?Promise.resolve(!1):m||(m=import(`../mask/MaskPhone.js`).then(e=>(f={...s,...e.default},p=!0,!0)),m)}function g(e){let t=window.getSelection();if(!t||t.rangeCount===0)return 0;let n=t.getRangeAt(0);if(!e.contains(n.startContainer))return 0;let r=document.createRange();return r.selectNodeContents(e),r.setEnd(n.startContainer,n.startOffset),r.toString().length}function _(e,t){if(t<=0)return 0;let n=0;for(let r=0;r<e.length;r++)if(/\d/.test(e[r])&&(n++,n===t))return r+1;return e.length}function v(e){let t=`+_(___) ___-__-__`,n=!0,r=0,i=0,a=``,o=e.replace(/\D/g,``);o===``&&(n=!0);let s=o.split(``),c=``;s.forEach(e=>{n&&(c+=e,f[c]!==void 0&&n?(n=!1,t=f[c].mask.replace(RegExp(`[0-9]`,`g`),`_`),a=f[c].code):(n&&(r=(``+c).length,t=`+${c}_(___) ___-__-__`.replace(RegExp(`[0-9]`,`g`),`_`),a=``),r>(``+c).length&&(n=!0,t=`+${c}_(___) ___-__-__`.replace(RegExp(`[0-9]`,`g`),`_`),a=``)))});let l=t.replace(/\D/g,``);return l.length>=o.length&&(o=l),{q:t.replace(/[_\d]/g,function(){return o.charAt(i++)||`_`}),i,v:o,f:a}}function y({value:n,form:s,onValue:f,onBlur:p,name:m=``,placeholder:y=``,label:x=``,error:S=``,hidden:C=!1,disabled:w=!1,className:T=``,after:E=``,before:D=``,inputmode:O=`tel`,id:k}){let{onNotice:A}=c(),j=!w,{value:M,version:N}=r(s,m,n),[,P]=l.useState(0),F=l.useRef(null),I=l.useRef(!1),L=(e,t)=>{let n=t.firstChild;if(!n||n.nodeType!==Node.TEXT_NODE)return;let r=n.textContent?.length??0,i=Math.max(0,Math.min(e,r)),a=document.createRange(),o=window.getSelection();o&&(a.setStart(n,i),a.collapse(!0),o.removeAllRanges(),o.addRange(a),t.focus())},R=e=>{let t=e.target,n=t.textContent||``,r=g(t),i=n.slice(0,r).replace(/\D/g,``).length,a=v(n);t.textContent=a.q;let o=_(a.q,i);a.q.length>0&&queueMicrotask(()=>{L(Math.min(o,a.q.length),t)});let c={value:a.q.replace(/\D/g,``),name:m||``};s&&m&&s.onValue(c),f&&f!==s?.onValue&&f(c)},z=e=>i.PasteOne(a(e));l.useLayoutEffect(()=>{if(I.current)return;let e=F.current;if(!e)return;let t=v(String(M||``));e.textContent!==t.q&&(e.textContent=t.q)},[M,N]);let B=e=>{e.preventDefault();let t=e.target;navigator.clipboard.writeText((t.textContent||``).replace(/\D/g,``)).then(function(){A(`Данные в буфер обмене`)},function(e){})},V=e=>{e.key===`Enter`&&e.preventDefault()},H=e=>{i.Blur(e),p&&p({value:(e.target.textContent||``).replace(/\D/g,``),name:m||``}),I.current=!1},U=e=>{I.current=!0,i.Focus({target:e.currentTarget}),h().then(e=>{if(!e)return;P(e=>e+1);let t=F.current;if(!t||document.activeElement!==t)return;let n=t.textContent||``,r=g(t),i=n.slice(0,r).replace(/\D/g,``).length,a=v(n);t.textContent!==a.q&&(t.textContent=a.q,queueMicrotask(()=>{L(Math.min(_(a.q,i),a.q.length),t)}))})},W={};y&&(W.placeholder=y),W.inputMode=O??`tel`;let G=String(M??``).replace(/\D/g,``);return C&&o(G)?null:d(t,{type:`input`,label:x,error:S,id:k,element_blok:{className:[T]},element_input:{className:[e.w]},children:[D?u(`span`,{className:e.affix,children:D}):null,u(b,{divRef:F,editable:j,disabled:w,label:x,placeholder:y,dd:W,onPaste:z,onInput:R,onKeyDown:V,onContextMenu:B,onBlur:H,onFocus:U}),E?u(`span`,{className:e.affix,children:E}):null]})}function b({divRef:e,editable:t,disabled:r,label:i,placeholder:a,dd:o,onPaste:s,onInput:c,onKeyDown:l,onContextMenu:d,onBlur:f,onFocus:p}){let m=n();return u(`div`,{ref:e,id:m?.controlId,onPaste:s,onInput:c,onKeyDown:l,onContextMenu:d,onBlur:f,onFocus:p,spellCheck:!1,role:`textbox`,"aria-label":i?void 0:a||`Телефон`,"aria-describedby":m?.describedBy,"aria-invalid":m?.errorId?!0:void 0,"aria-disabled":!t,tabIndex:r?-1:0,"data-disabled":!t,contentEditable:t?`plaintext-only`:!1,suppressContentEditableWarning:!0,...o})}y.displayName=`PhoneField`;export{y as default};
1
+ import e from"../styles/Field.module.js";import t,{useFieldA11y as n}from"../core/Field.js";import{useFormFieldState as r}from"../hooks/use.js";import{createFieldEmit as i}from"./emit.js";import a,{asEditableClipboard as o}from"../events/onEvent.js";import{isEmptyTextLike as s}from"./visibility.js";import{PHONE_MASK_DEFAULTS as c}from"../mask/phoneDefaults.js";import{useFormInit as l}from"../FormInitContext.js";import u from"react";import{jsx as d,jsxs as f}from"react/jsx-runtime";var p={...c},m=!1,h=null;function g(){return m?Promise.resolve(!1):h||(h=import(`../mask/MaskPhone.js`).then(e=>(p={...c,...e.default},m=!0,!0)),h)}function _(e){let t=window.getSelection();if(!t||t.rangeCount===0)return 0;let n=t.getRangeAt(0);if(!e.contains(n.startContainer))return 0;let r=document.createRange();return r.selectNodeContents(e),r.setEnd(n.startContainer,n.startOffset),r.toString().length}function v(e,t){if(t<=0)return 0;let n=0;for(let r=0;r<e.length;r++)if(/\d/.test(e[r])&&(n++,n===t))return r+1;return e.length}function y(e){let t=`+_(___) ___-__-__`,n=!0,r=0,i=0,a=``,o=e.replace(/\D/g,``);o===``&&(n=!0);let s=o.split(``),c=``;s.forEach(e=>{n&&(c+=e,p[c]!==void 0&&n?(n=!1,t=p[c].mask.replace(RegExp(`[0-9]`,`g`),`_`),a=p[c].code):(n&&(r=(``+c).length,t=`+${c}_(___) ___-__-__`.replace(RegExp(`[0-9]`,`g`),`_`),a=``),r>(``+c).length&&(n=!0,t=`+${c}_(___) ___-__-__`.replace(RegExp(`[0-9]`,`g`),`_`),a=``)))});let l=t.replace(/\D/g,``);return l.length>=o.length&&(o=l),{q:t.replace(/[_\d]/g,function(){return o.charAt(i++)||`_`}),i,v:o,f:a}}function b({value:n,form:c,onValue:p,onBlur:m,name:h=``,placeholder:b=``,label:S=``,error:C=``,hidden:w=!1,disabled:T=!1,className:E=``,after:D=``,before:O=``,inputmode:k=`tel`,id:A}){let{onNotice:j}=l(),M=!T,{value:N,version:P}=r(c,h,n),[,F]=u.useState(0),I=u.useRef(null),L=u.useRef(!1),R=(e,t)=>{let n=t.firstChild;if(!n||n.nodeType!==Node.TEXT_NODE)return;let r=n.textContent?.length??0,i=Math.max(0,Math.min(e,r)),a=document.createRange(),o=window.getSelection();o&&(a.setStart(n,i),a.collapse(!0),o.removeAllRanges(),o.addRange(a),t.focus())},z=i(c,h,p),B=e=>{let t=e.target,n=t.textContent||``,r=_(t),i=n.slice(0,r).replace(/\D/g,``).length,a=y(n);t.textContent=a.q;let o=v(a.q,i);a.q.length>0&&queueMicrotask(()=>{R(Math.min(o,a.q.length),t)}),z(a.q.replace(/\D/g,``))},V=e=>a.PasteOne(o(e));u.useLayoutEffect(()=>{if(L.current)return;let e=I.current;if(!e)return;let t=y(String(N||``));e.textContent!==t.q&&(e.textContent=t.q)},[N,P]);let H=e=>{e.preventDefault();let t=e.target;navigator.clipboard.writeText((t.textContent||``).replace(/\D/g,``)).then(function(){j(`Данные в буфер обмене`)},function(e){})},U=e=>{e.key===`Enter`&&e.preventDefault()},W=e=>{a.Blur(e),m&&m({value:(e.target.textContent||``).replace(/\D/g,``),name:h||``}),L.current=!1},G=e=>{L.current=!0,a.Focus({target:e.currentTarget}),g().then(e=>{if(!e)return;F(e=>e+1);let t=I.current;if(!t||document.activeElement!==t)return;let n=t.textContent||``,r=_(t),i=n.slice(0,r).replace(/\D/g,``).length,a=y(n);t.textContent!==a.q&&(t.textContent=a.q,queueMicrotask(()=>{R(Math.min(v(a.q,i),a.q.length),t)}))})},K={};b&&(K.placeholder=b),K.inputMode=k??`tel`;let q=String(N??``).replace(/\D/g,``);return w&&s(q)?null:f(t,{type:`input`,label:S,error:C,id:A,element_blok:{className:[E]},element_input:{className:[e.w],props:{"data-disabled":T||!M?`true`:void 0}},children:[O?d(`span`,{className:e.a,children:O}):null,d(x,{divRef:I,editable:M,disabled:T,label:S,placeholder:b,dd:K,onPaste:V,onInput:B,onKeyDown:U,onContextMenu:H,onBlur:W,onFocus:G}),D?d(`span`,{className:e.a,children:D}):null]})}function x({divRef:e,editable:t,disabled:r,label:i,placeholder:a,dd:o,onPaste:s,onInput:c,onKeyDown:l,onContextMenu:u,onBlur:f,onFocus:p}){let m=n();return d(`div`,{ref:e,id:m?.controlId,onPaste:s,onInput:c,onKeyDown:l,onContextMenu:u,onBlur:f,onFocus:p,spellCheck:!1,role:`textbox`,"aria-label":i?void 0:a||`Телефон`,"aria-describedby":m?.describedBy,"aria-invalid":m?.errorId?!0:void 0,"aria-disabled":!t,tabIndex:r?-1:0,"data-disabled":t?void 0:`true`,contentEditable:t?`plaintext-only`:!1,suppressContentEditableWarning:!0,...o})}b.displayName=`PhoneField`;export{b as default};
@@ -14,8 +14,10 @@ export type TRadio = TInput & {
14
14
  options?: RadioOptions;
15
15
  /** Горизонтальный ряд вместо колонки */
16
16
  inline?: boolean;
17
+ /** Кружок: top | center | bottom относительно текста. По умолчанию center */
18
+ align?: "top" | "center" | "bottom";
17
19
  };
18
- declare function RadioField({ value, form, onValue, onBlur: onBlurField, name, placeholder, label, error, hidden, disabled, className, after, before, options, inline, }: TRadio): import("react/jsx-runtime").JSX.Element | null;
20
+ declare function RadioField({ value, form, onValue, onBlur: onBlurField, name, placeholder, label, error, hidden, disabled, className, after, before, options, inline, align, }: TRadio): import("react/jsx-runtime").JSX.Element | null;
19
21
  declare namespace RadioField {
20
22
  var displayName: string;
21
23
  }
@@ -1 +1 @@
1
- import e from"../styles/Field.module.js";import t from"../core/Field.js";import{useFormFieldState as n}from"../hooks/use.js";import r from"react";import{jsx as i,jsxs as a}from"react/jsx-runtime";function o(e){return e?Array.isArray(e)?e.map(e=>({id:e.id??e.i??``,label:e.n||``,hidden:e.s===0})).filter(e=>e.label.length>0&&e.id!==``):Object.keys(e).map(t=>{let n=e[t],r=Number(t);return{id:Number.isFinite(r)&&String(r)===t?r:t,label:n?.n||``,hidden:n?.s===0}}).filter(e=>e.label.length>0):[]}function s(e,t){return e===t?!0:String(e)===String(t)}function c({value:c=``,form:l,onValue:u,onBlur:d,name:f=``,placeholder:p=``,label:m=``,error:h=``,hidden:g=!1,disabled:_=!1,className:v=``,after:y=``,before:b=``,options:x,inline:S=!1}){let{value:C}=n(l,f,c),w=!_,T=o(x).filter(e=>!e.hidden),E=r.useId(),D=e=>{let t={value:e,name:f};l&&f&&l.setValue(t),u&&u!==l?.onValue&&u(t)};return g&&(C==null||C===``)?null:a(t,{type:`radio`,label:m,error:h,element_blok:{className:[v||``]},element_input:{className:[e.radio,S?e.radioInline:``],props:{"data-disabled":_||!w?`true`:void 0,role:`radiogroup`,"aria-label":m||p||`Выбор`}},children:[b?i(`span`,{className:e.affix,children:b}):null,i(`div`,{children:T.map(t=>{let n=s(C,t.id);return a(`button`,{type:`button`,className:e.radioItem,role:`radio`,"aria-checked":n,"aria-disabled":_||!w?!0:void 0,disabled:_||!w,name:E,onClick:()=>{w&&D(t.id)},onBlur:()=>{!d||!f||d({value:l?l.getValue(f,C):C,name:f})},children:[i(`span`,{className:e.radioDot,"aria-hidden":!0,children:n?i(`span`,{className:e.radioDotFill}):null}),i(`span`,{className:e.radioText,children:t.label})]},String(t.id))})}),y?i(`span`,{className:e.affix,children:y}):null]})}c.displayName=`RadioField`;export{c as default};
1
+ import e from"../styles/Field.module.js";import t from"../core/Field.js";import{useFormFieldState as n}from"../hooks/use.js";import{createFieldEmit as r}from"./emit.js";import i from"../styles/Radio.module.js";import a from"react";import{jsx as o,jsxs as s}from"react/jsx-runtime";function c(e){return e?Array.isArray(e)?e.map(e=>({id:e.id??e.i??``,label:e.n||``,hidden:e.s===0})).filter(e=>e.label.length>0&&e.id!==``):Object.keys(e).map(t=>{let n=e[t],r=Number(t);return{id:Number.isFinite(r)&&String(r)===t?r:t,label:n?.n||``,hidden:n?.s===0}}).filter(e=>e.label.length>0):[]}function l(e,t){return e===t?!0:String(e)===String(t)}function u({value:u=``,form:d,onValue:f,onBlur:p,name:m=``,placeholder:h=``,label:g=``,error:_=``,hidden:v=!1,disabled:y=!1,className:b=``,after:x=``,before:S=``,options:C,inline:w=!1,align:T=`center`}){let{value:E}=n(d,m,u),D=!y,O=c(C).filter(e=>!e.hidden),k=a.useId(),A=e=>{r(d,m,f)(e,!0)};return v&&(E==null||E===``)?null:s(t,{type:`radio`,label:g,error:_,element_blok:{className:[b||``]},element_input:{className:[i.d,w?i.i:``],props:{"data-disabled":y||!D?`true`:void 0,role:`radiogroup`,"aria-label":g||h||`Выбор`}},children:[S?o(`span`,{className:e.a,children:S}):null,o(`div`,{children:O.map(e=>{let t=l(E,e.id);return s(`button`,{type:`button`,className:i.t,role:`radio`,"aria-checked":t,"aria-disabled":y||!D?!0:void 0,disabled:y||!D,"data-align":T,name:k,onClick:()=>{D&&A(e.id)},onBlur:()=>{!p||!m||p({value:d?d.getValue(m,E):E,name:m})},children:[o(`span`,{className:i.o,"aria-hidden":!0,children:t?o(`span`,{className:i.f}):null}),o(`span`,{className:i.x,children:e.label})]},String(e.id))})}),x?o(`span`,{className:e.a,children:x}):null]})}u.displayName=`RadioField`;export{u as default};
@@ -1,16 +1,19 @@
1
1
  import { TInput } from './type';
2
- /** Поле «диапазон»: кастомный трек (div), визуально как «таблетка» с заливкой, без нативного range */
2
+ /** `bar` толстая «таблетка» с заливкой; `line` тонкая линия и круглый thumb */
3
+ export type TRangeVariant = "bar" | "line";
4
+ /** Поле «диапазон»: кастомный трек (div), без нативного range */
3
5
  export type TRange = TInput & {
4
6
  min?: number;
5
7
  max?: number;
6
8
  step?: number;
9
+ /**
10
+ * `bar` — iOS-прогресс (заливка слева),
11
+ * `line` — тонкий трек и кружок (как системный range).
12
+ */
13
+ variant?: TRangeVariant;
7
14
  };
8
- /** @deprecated используйте `TRange` */
9
- export type TProgress = TRange;
10
- declare function RangeField({ value, form, onValue, onBlur: onBlurField, name, placeholder, label, error, hidden, disabled, className, after, before, min, max, step, }: TRange): import("react/jsx-runtime").JSX.Element | null;
15
+ declare function RangeField({ value, form, onValue, onBlur: onBlurField, name, placeholder, label, error, hidden, disabled, className, after, before, min, max, step, variant, }: TRange): import("react/jsx-runtime").JSX.Element | null;
11
16
  declare namespace RangeField {
12
17
  var displayName: string;
13
18
  }
14
19
  export default RangeField;
15
- /** Псевдоним для обратной совместимости */
16
- export { RangeField as ProgressField };
@@ -1 +1 @@
1
- import e from"../styles/Field.module.js";import t from"../core/Field.js";import{useFormFieldState as n}from"../hooks/use.js";import r from"react";import{jsx as i,jsxs as a}from"react/jsx-runtime";function o(e,t,n){let r=e;return Number.isFinite(r)||(r=t),Math.min(n,Math.max(t,r))}function s(e,t,n,r){return o(!Number.isFinite(r)||r<=0?e:t+Math.round((e-t)/r)*r,t,n)}function c({value:c=0,form:l,onValue:u,onBlur:d,name:f=``,placeholder:p=``,label:m=``,error:h=``,hidden:g=!1,disabled:_=!1,className:v=``,after:y=``,before:b=``,min:x=0,max:S=100,step:C=1}){let{value:w}=n(l,f,c),T=o(Number(w),x,S),E=S===x?0:(T-x)/(S-x)*100,D=E>=99.999,O=!_,k=r.useRef(null),A=r.useCallback(e=>{let t={value:s(e,x,S,C),name:f||``};l&&f&&l.setValue(t),u&&u!==l?.onValue&&u(t)},[l,f,u,x,S,C]),j=r.useCallback(e=>{let t=k.current;if(!t)return x;let n=t.getBoundingClientRect(),r=n.width||1;return s(x+(e-n.left)/r*(S-x),x,S,C)},[x,S,C]),M=e=>{O&&(e.preventDefault(),e.currentTarget.setPointerCapture(e.pointerId),A(j(e.clientX)))},N=e=>{O&&e.currentTarget.hasPointerCapture(e.pointerId)&&A(j(e.clientX))},P=e=>{try{e.currentTarget.releasePointerCapture(e.pointerId)}catch{}},F=e=>{if(!O)return;let t=T;if(e.key===`ArrowRight`||e.key===`ArrowUp`)t=T+C;else if(e.key===`ArrowLeft`||e.key===`ArrowDown`)t=T-C;else if(e.key===`Home`)t=x;else if(e.key===`End`)t=S;else if(e.key===`PageUp`)t=T+C*10;else if(e.key===`PageDown`)t=T-C*10;else return;e.preventDefault(),A(s(t,x,S,C))},I=()=>{if(!d||!f)return;let e=l&&f?l.getValue(f,c):T;d({value:o(Number(e),x,S),name:f})};return g&&(w==null||w===``)?null:a(t,{type:`range`,label:m,error:h,element_blok:{className:[v||``]},element_input:{className:[e.w,e.range],props:{"data-disabled":_||!O?`true`:void 0}},children:[b?i(`span`,{className:e.affix,children:b}):null,i(`div`,{children:i(`div`,{ref:k,className:e.rangeTrack,role:`slider`,tabIndex:O?0:-1,"aria-label":m||p||`Диапазон`,"aria-valuemin":x,"aria-valuemax":S,"aria-valuenow":T,"data-disabled":_||!O?`true`:void 0,onPointerDown:M,onPointerMove:N,onPointerUp:P,onPointerCancel:P,onKeyDown:F,onBlur:I,children:i(`div`,{className:D?`${e.rangeFill} ${e.rangeFillFull}`:e.rangeFill,style:{width:`${E}%`},"aria-hidden":!0})})}),y?i(`span`,{className:e.affix,children:y}):null]})}c.displayName=`RangeField`;export{c as default};
1
+ import e from"../styles/Field.module.js";import t from"../core/Field.js";import{useFormFieldState as n}from"../hooks/use.js";import{createFieldEmit as r}from"./emit.js";import i from"react";import{jsx as a,jsxs as o}from"react/jsx-runtime";function s(e,t,n){let r=e;return Number.isFinite(r)||(r=t),Math.min(n,Math.max(t,r))}function c(e,t,n,r){return s(!Number.isFinite(r)||r<=0?e:t+Math.round((e-t)/r)*r,t,n)}function l({value:l=0,form:u,onValue:d,onBlur:f,name:p=``,placeholder:m=``,label:h=``,error:g=``,hidden:_=!1,disabled:v=!1,className:y=``,after:b=``,before:x=``,min:S=0,max:C=100,step:w=1,variant:T=`bar`}){let{value:E}=n(u,p,l),D=s(Number(E),S,C),O=C===S?0:(D-S)/(C-S)*100,k=O>=99.999,A=!v,j=i.useRef(null),M=i.useCallback(e=>{let t=c(e,S,C,w);r(u,p,d)(t,!0)},[u,p,d,S,C,w]),N=i.useCallback(e=>{let t=j.current;if(!t)return S;let n=t.getBoundingClientRect(),r=n.width||1;return c(S+(e-n.left)/r*(C-S),S,C,w)},[S,C,w]),P=e=>{A&&(e.preventDefault(),e.currentTarget.setPointerCapture(e.pointerId),M(N(e.clientX)))},F=e=>{A&&e.currentTarget.hasPointerCapture(e.pointerId)&&M(N(e.clientX))},I=e=>{try{e.currentTarget.releasePointerCapture(e.pointerId)}catch{}},L=e=>{if(!A)return;let t=D;if(e.key===`ArrowRight`||e.key===`ArrowUp`)t=D+w;else if(e.key===`ArrowLeft`||e.key===`ArrowDown`)t=D-w;else if(e.key===`Home`)t=S;else if(e.key===`End`)t=C;else if(e.key===`PageUp`)t=D+w*10;else if(e.key===`PageDown`)t=D-w*10;else return;e.preventDefault(),M(c(t,S,C,w))},R=()=>{if(!f||!p)return;let e=u&&p?u.getValue(p,l):D;f({value:s(Number(e),S,C),name:p})};return _&&(E==null||E===``)?null:o(t,{type:`range`,label:h,error:g,element_blok:{className:[y||``]},element_input:{className:[e.w,e.r],props:{"data-disabled":v||!A?`true`:void 0,"data-variant":T}},children:[x?a(`span`,{className:e.a,children:x}):null,a(`div`,{children:o(`div`,{ref:j,className:e.k,role:`slider`,tabIndex:A?0:-1,"aria-label":h||m||`Диапазон`,"aria-valuemin":S,"aria-valuemax":C,"aria-valuenow":D,"data-disabled":v||!A?`true`:void 0,onPointerDown:P,onPointerMove:F,onPointerUp:I,onPointerCancel:I,onKeyDown:L,onBlur:R,children:[a(`div`,{className:k?`${e.u} ${e.v}`:e.u,style:{width:`${O}%`},"aria-hidden":!0}),T===`line`?a(`div`,{className:e.h,style:{left:`${O}%`},"aria-hidden":!0}):null]})}),b?a(`span`,{className:e.a,children:b}):null]})}l.displayName=`RangeField`;export{l as default};
@@ -1 +1 @@
1
- import e from"../styles/Field.module.js";import t from"../core/Field.js";import{useFormFieldState as n}from"../hooks/use.js";import r from"react";import{jsx as i,jsxs as a}from"react/jsx-runtime";function o(e,t){return Number.isFinite(e)?Math.min(t,Math.max(0,Math.round(e))):0}function s({value:s=0,form:c,onValue:l,onBlur:u,name:d=``,placeholder:f=``,label:p=``,error:m=``,hidden:h=!1,disabled:g=!1,className:_=``,after:v=``,before:y=``,max:b=5,allowClear:x=!0}){let{value:S}=n(c,d,s),C=o(Number(S),b),w=!g,[T,E]=r.useState(0),D=e=>{let t={value:e,name:d};c&&d&&c.setValue(t),l&&l!==c?.onValue&&l(t)};if(h&&!C)return null;let O=T||C;return a(t,{type:`rating`,label:p,error:m,element_blok:{className:[_||``]},element_input:{className:[e.rating],props:{"data-disabled":g||!w?`true`:void 0}},children:[y?i(`span`,{className:e.affix,children:y}):null,i(`div`,{role:`slider`,"aria-label":p||f||`Оценка`,"aria-valuemin":0,"aria-valuemax":b,"aria-valuenow":C,tabIndex:w?0:-1,onMouseLeave:()=>E(0),onBlur:()=>{E(0),u?.({value:C,name:d})},onKeyDown:e=>{if(!w)return;let t=C;if(e.key===`ArrowRight`||e.key===`ArrowUp`)t=Math.min(b,C+1);else if(e.key===`ArrowLeft`||e.key===`ArrowDown`)t=Math.max(0,C-1);else if(e.key===`Home`)t=0;else if(e.key===`End`)t=b;else return;e.preventDefault(),D(t)},children:Array.from({length:b},(t,n)=>{let r=n+1;return i(`button`,{type:`button`,className:r<=O?`${e.ratingStar} ${e.ratingStarOn}`:e.ratingStar,"aria-label":`${r} из ${b}`,disabled:!w,onMouseEnter:()=>w&&E(r),onClick:()=>{w&&D(x&&C===r?0:r)},children:`★`},r)})}),v?i(`span`,{className:e.affix,children:v}):null]})}s.displayName=`RatingField`;export{s as default};
1
+ import e from"../styles/Field.module.js";import t from"../core/Field.js";import{useFormFieldState as n}from"../hooks/use.js";import{createFieldEmit as r}from"./emit.js";import i from"../styles/Rating.module.js";import a from"react";import{jsx as o,jsxs as s}from"react/jsx-runtime";function c(e,t){return Number.isFinite(e)?Math.min(t,Math.max(0,Math.round(e))):0}function l({value:l=0,form:u,onValue:d,onBlur:f,name:p=``,placeholder:m=``,label:h=``,error:g=``,hidden:_=!1,disabled:v=!1,className:y=``,after:b=``,before:x=``,max:S=5,allowClear:C=!0}){let{value:w}=n(u,p,l),T=c(Number(w),S),E=!v,[D,O]=a.useState(0),k=e=>{r(u,p,d)(e,!0)};if(_&&!T)return null;let A=D||T;return s(t,{type:`rating`,label:h,error:g,element_blok:{className:[y||``]},element_input:{className:[i.r],props:{"data-disabled":v||!E?`true`:void 0}},children:[x?o(`span`,{className:e.a,children:x}):null,o(`div`,{role:`slider`,"aria-label":h||m||`Оценка`,"aria-valuemin":0,"aria-valuemax":S,"aria-valuenow":T,tabIndex:E?0:-1,onMouseLeave:()=>O(0),onBlur:()=>{O(0),f?.({value:T,name:p})},onKeyDown:e=>{if(!E)return;let t=T;if(e.key===`ArrowRight`||e.key===`ArrowUp`)t=Math.min(S,T+1);else if(e.key===`ArrowLeft`||e.key===`ArrowDown`)t=Math.max(0,T-1);else if(e.key===`Home`)t=0;else if(e.key===`End`)t=S;else return;e.preventDefault(),k(t)},children:Array.from({length:S},(e,t)=>{let n=t+1;return o(`button`,{type:`button`,className:n<=A?`${i.s} ${i.o}`:i.s,"aria-label":`${n} из ${S}`,disabled:!E,onMouseEnter:()=>E&&O(n),onClick:()=>{E&&k(C&&T===n?0:n)},children:`★`},n)})}),b?o(`span`,{className:e.a,children:b}):null]})}l.displayName=`RatingField`;export{l as default};
@@ -1 +1 @@
1
- import e from"../styles/Field.module.js";import t from"../core/Field.js";import{useFormFieldState as n}from"../hooks/use.js";import{isEmptyTextLike as r}from"./visibility.js";import i from"react";import{jsx as a,jsxs as o}from"react/jsx-runtime";function s({value:s=``,form:c,onValue:l,onBlur:u,name:d=``,placeholder:f=``,label:p=``,error:m=``,hidden:h=!1,disabled:g=!1,className:_=``,after:v=``,before:y=``,maxLength:b,spellCheck:x=!0,toolbar:S=!0}){let{value:C,version:w}=n(c,d,s),T=!g,E=typeof C==`string`?C:``,D=i.useRef(null),O=i.useRef(!1);i.useLayoutEffect(()=>{if(O.current)return;let e=D.current;e&&e.innerHTML!==E&&(e.innerHTML=E||``)},[E,w]);let k=(e,t=!1)=>{let n=e;if(b&&n.replace(/<[^>]+>/g,``).length>b)return;let r={value:n,name:d};c&&d&&(t?c.setValue(r):c.onValue(r)),l&&l!==c?.onValue&&l(r)},A=e=>{if(T){D.current?.focus();try{document.execCommand(e,!1)}catch{}k(D.current?.innerHTML||``)}};if(h&&r(E.replace(/<[^>]+>/g,``)))return null;let j={};return f&&!E&&(j.placeholder=f),T&&(j.edit=``),o(t,{type:`richtext`,label:p,error:m,element_blok:{className:[_||``]},element_input:{className:[e.rich],props:{"data-disabled":g||!T?`true`:void 0}},children:[y?a(`span`,{className:e.affix,children:y}):null,o(`div`,{className:e.richWrap,children:[S?o(`div`,{className:e.richToolbar,role:`toolbar`,children:[a(`button`,{type:`button`,className:e.richBtn,disabled:!T,"aria-label":`Жирный`,onMouseDown:e=>e.preventDefault(),onClick:()=>A(`bold`),children:`B`}),a(`button`,{type:`button`,className:e.richBtn,disabled:!T,"aria-label":`Курсив`,onMouseDown:e=>e.preventDefault(),onClick:()=>A(`italic`),children:a(`em`,{children:`I`})}),a(`button`,{type:`button`,className:e.richBtn,disabled:!T,"aria-label":`Подчёркивание`,onMouseDown:e=>e.preventDefault(),onClick:()=>A(`underline`),children:a(`u`,{children:`U`})}),a(`button`,{type:`button`,className:e.richBtn,disabled:!T,"aria-label":`Маркированный список`,onMouseDown:e=>e.preventDefault(),onClick:()=>A(`insertUnorderedList`),children:`•`}),a(`button`,{type:`button`,className:e.richBtn,disabled:!T,"aria-label":`Нумерованный список`,onMouseDown:e=>e.preventDefault(),onClick:()=>A(`insertOrderedList`),children:`1.`})]}):null,a(`div`,{ref:D,className:e.richEditor,contentEditable:T,suppressContentEditableWarning:!0,spellCheck:x,role:`textbox`,"aria-multiline":!0,"aria-label":p||f||`Текст`,tabIndex:T?0:-1,onFocus:()=>{O.current=!0},onInput:()=>k(D.current?.innerHTML||``),onBlur:()=>{O.current=!1;let e=D.current?.innerHTML||``;k(e,!0),u?.({value:e,name:d})},...j})]}),v?a(`span`,{className:e.affix,children:v}):null]})}s.displayName=`RichTextField`;export{s as default};
1
+ import e from"../styles/Field.module.js";import t from"../core/Field.js";import{useFormFieldState as n}from"../hooks/use.js";import{createFieldEmit as r}from"./emit.js";import{isEmptyTextLike as i}from"./visibility.js";import a from"../styles/Rich.module.js";import o from"react";import{jsx as s,jsxs as c}from"react/jsx-runtime";function l({value:l=``,form:u,onValue:d,onBlur:f,name:p=``,placeholder:m=``,label:h=``,error:g=``,hidden:_=!1,disabled:v=!1,className:y=``,after:b=``,before:x=``,maxLength:S,spellCheck:C=!0,toolbar:w=!0}){let{value:T,version:E}=n(u,p,l),D=!v,O=typeof T==`string`?T:``,k=o.useRef(null),A=o.useRef(!1);o.useLayoutEffect(()=>{if(A.current)return;let e=k.current;e&&e.innerHTML!==O&&(e.innerHTML=O||``)},[O,E]);let j=r(u,p,d),M=(e,t=!1)=>{S&&e.replace(/<[^>]+>/g,``).length>S||j(e,t)},N=e=>{if(D){k.current?.focus();try{document.execCommand(e,!1)}catch{}M(k.current?.innerHTML||``)}};if(_&&i(O.replace(/<[^>]+>/g,``)))return null;let P={};return m&&!O&&(P.placeholder=m),D&&(P.edit=``),c(t,{type:`richtext`,label:h,error:g,element_blok:{className:[y||``]},element_input:{className:[a.r],props:{"data-disabled":v||!D?`true`:void 0}},children:[x?s(`span`,{className:e.a,children:x}):null,c(`div`,{className:a.w,children:[w?c(`div`,{className:a.t,role:`toolbar`,children:[s(`button`,{type:`button`,className:a.b,disabled:!D,"aria-label":`Жирный`,onMouseDown:e=>e.preventDefault(),onClick:()=>N(`bold`),children:`B`}),s(`button`,{type:`button`,className:a.b,disabled:!D,"aria-label":`Курсив`,onMouseDown:e=>e.preventDefault(),onClick:()=>N(`italic`),children:s(`em`,{children:`I`})}),s(`button`,{type:`button`,className:a.b,disabled:!D,"aria-label":`Подчёркивание`,onMouseDown:e=>e.preventDefault(),onClick:()=>N(`underline`),children:s(`u`,{children:`U`})}),s(`button`,{type:`button`,className:a.b,disabled:!D,"aria-label":`Маркированный список`,onMouseDown:e=>e.preventDefault(),onClick:()=>N(`insertUnorderedList`),children:`•`}),s(`button`,{type:`button`,className:a.b,disabled:!D,"aria-label":`Нумерованный список`,onMouseDown:e=>e.preventDefault(),onClick:()=>N(`insertOrderedList`),children:`1.`})]}):null,s(`div`,{ref:k,className:a.e,contentEditable:D,suppressContentEditableWarning:!0,spellCheck:C,role:`textbox`,"aria-multiline":!0,"aria-label":h||m||`Текст`,tabIndex:D?0:-1,onFocus:()=>{A.current=!0},onInput:()=>M(k.current?.innerHTML||``),onBlur:()=>{A.current=!1;let e=k.current?.innerHTML||``;M(e,!0),f?.({value:e,name:p})},...P})]}),b?s(`span`,{className:e.a,children:b}):null]})}l.displayName=`RichTextField`;export{l as default};
@@ -1 +1 @@
1
- import e from"../styles/Field.module.js";import t from"../core/Field.js";import{useFormFieldState as n}from"../hooks/use.js";import{acquireOverlayZIndex as r,releaseOverlayZIndex as i}from"../overlayZ.js";import a from"../styles/Select.module.js";import o,{useEffect as s,useState as c}from"react";import{Fragment as l,jsx as u,jsxs as d}from"react/jsx-runtime";import{createPortal as f}from"react-dom";function p({value:r=0,form:i,onValue:c,name:p=``,placeholder:m=``,label:g,error:_,hidden:v=!1,disabled:y=!1,className:b,after:x=``,before:S=``,options:C,order:w,size:T=`md`}){let[E,D]=o.useState(!1),[O,k]=o.useState(0),[A,j]=o.useState(null),M=o.useRef(null),N=o.useId(),P=o.useCallback(()=>{let e=M.current;if(!e)return;let t=e.getBoundingClientRect();j(e=>e&&e.top===t.top&&e.left===t.left&&e.width===t.width&&e.height===t.height&&e.bottom===t.bottom?e:t)},[]);s(()=>{if(!E)return;P();let e=()=>P();return window.addEventListener(`scroll`,e,!0),window.addEventListener(`resize`,e),()=>{window.removeEventListener(`scroll`,e,!0),window.removeEventListener(`resize`,e)}},[E,P]);let{value:F}=n(i,p,r??0),I=Number(F),L=[];C&&(L=Array.isArray(C)?C.map(e=>({id:e.id??e.i??0,label:e.n||``,hidden:e.s===0})).filter(e=>e.id!==0&&e.label.length>0):Object.keys(C).map(e=>{let t=Number(e),n=C[t];return{id:t,label:n?.n||``,hidden:n?.s===0}}).filter(e=>e.label.length>0));let R=(()=>{if(!w||w.length===0)return L;let e=new Map(L.map(e=>[e.id,e]));return w.map(t=>e.get(t)).filter(e=>!!e)})().filter(e=>!e.hidden),z=e=>R.find(t=>t.id===e)?.label,B=E&&R.length>0?`${N}-opt-${O}`:void 0,V=e=>{let t={value:e,name:p};i&&p&&i.setValue(t),c&&c!==i?.onValue&&c(t)},H=e=>{if(R.length===0||y)return;let t=R.findIndex(e=>e.id===I);M.current=e;let n=e.getBoundingClientRect(),r=t>=0?t:0;j(n),k(r),D(!0)},U=e=>{H(e.currentTarget)},W=e=>{if(!y&&R.length!==0){if(!E&&(e.key===`ArrowDown`||e.key===`Enter`||e.key===` `)){e.preventDefault(),H(e.currentTarget);return}if(E){if(e.key===`Escape`){e.preventDefault(),D(!1);return}if(e.key===`ArrowDown`){e.preventDefault(),k(e=>(e+1)%R.length);return}if(e.key===`ArrowUp`){e.preventDefault(),k(e=>e-1<0?R.length-1:e-1);return}if(e.key===`Enter`){e.preventDefault();let t=R[O];t&&V(t.id),D(!1)}}}},G={};m&&(G.placeholder=m);let K=z(I),q=(K===void 0||K===``)&&!!m,J=I===0||z(I)===void 0;return v&&J?``:d(l,{children:[d(t,{type:`select`,label:g,element_blok:{className:[b||``]},error:_,size:T,element_input:{className:[a.f],props:{onClick:U,onKeyDown:W,tabIndex:y?-1:0,role:`combobox`,"aria-expanded":E,"aria-haspopup":`listbox`,"aria-controls":N,...B?{"aria-activedescendant":B}:{},"aria-disabled":y,"data-disabled":y}},children:[S?u(`span`,{className:e.affix,children:S}):null,u(`div`,{...G,className:q?a.placeholderValue:void 0,children:K??m??``}),x?u(`span`,{className:e.affix,children:x}):null]}),E&&f(u(h,{parent:A||void 0,onValue:V,className:b,items:R,setOpen:D,listId:N,activeIndex:O,currentValue:I}),document.body)]})}p.displayName=`SelectField`;var m=o.memo(p),h=({onValue:e,parent:t,className:n,items:o,setOpen:f,listId:p,activeIndex:m,currentValue:h})=>{let[_]=c(()=>r());if(s(()=>()=>i(_),[_]),!t)return null;let v=()=>{f(!1)},y=t=>{f(!1),e(t)},b=Math.min(300,Math.max(52,o.length*52+8)),x=window.innerHeight-t.bottom-6-8,S=t.top-6-8,C=x<Math.min(b,160)&&S>x,w=Math.max(t.width,260),T=Math.min(Math.max(8,t.left),window.innerWidth-w-8);return d(l,{children:[u(`div`,{className:a.o,style:{zIndex:_},onClick:v,"aria-hidden":!0}),u(`div`,{className:[a.l,n].filter(e=>e!==void 0).join(` `),style:{...C?{bottom:`${window.innerHeight-t.top+6}px`}:{top:`${t.bottom+6}px`},left:T+`px`,width:w,zIndex:_+1},children:u(g,{listId:p,items:o,link:y,activeIndex:m,currentValue:h})})]})},g=({listId:e,items:t,link:n,activeIndex:r,currentValue:i})=>u(`ul`,{id:e,role:`listbox`,children:t.map((t,a)=>u(`li`,{id:`${e}-opt-${a}`,role:`option`,"aria-selected":i===t.id,"data-focus":r===a?`true`:`false`,onClick:()=>n(t.id),children:t.label},t.id))});export{m as default};
1
+ import e from"../styles/Field.module.js";import t from"../core/Field.js";import{useFormFieldState as n}from"../hooks/use.js";import{createFieldEmit as r}from"./emit.js";import{acquireOverlayZIndex as i,releaseOverlayZIndex as a}from"../overlayZ.js";import o from"../styles/Select.module.js";import s,{useEffect as c,useState as l}from"react";import{Fragment as u,jsx as d,jsxs as f}from"react/jsx-runtime";import{createPortal as p}from"react-dom";function m({value:i=0,form:a,onValue:l,name:m=``,placeholder:h=``,label:_,error:v,hidden:y=!1,disabled:b=!1,className:x,after:S=``,before:C=``,options:w,order:T,size:E=`m`}){let[D,O]=s.useState(!1),[k,A]=s.useState(0),[j,M]=s.useState(null),N=s.useRef(null),P=s.useId(),F=s.useCallback(()=>{let e=N.current;if(!e)return;let t=e.getBoundingClientRect();M(e=>e&&e.top===t.top&&e.left===t.left&&e.width===t.width&&e.height===t.height&&e.bottom===t.bottom?e:t)},[]);c(()=>{if(!D)return;F();let e=()=>F();return window.addEventListener(`scroll`,e,!0),window.addEventListener(`resize`,e),()=>{window.removeEventListener(`scroll`,e,!0),window.removeEventListener(`resize`,e)}},[D,F]);let{value:I}=n(a,m,i??0),L=Number(I),R=[];w&&(R=Array.isArray(w)?w.map(e=>({id:e.id??e.i??0,label:e.n||``,hidden:e.s===0})).filter(e=>e.id!==0&&e.label.length>0):Object.keys(w).map(e=>{let t=Number(e),n=w[t];return{id:t,label:n?.n||``,hidden:n?.s===0}}).filter(e=>e.label.length>0));let z=(()=>{if(!T||T.length===0)return R;let e=new Map(R.map(e=>[e.id,e]));return T.map(t=>e.get(t)).filter(e=>!!e)})().filter(e=>!e.hidden),B=e=>z.find(t=>t.id===e)?.label,V=D&&z.length>0?`${P}-opt-${k}`:void 0,H=e=>{r(a,m,l)(e,!0)},U=e=>{if(z.length===0||b)return;let t=z.findIndex(e=>e.id===L);N.current=e;let n=e.getBoundingClientRect(),r=t>=0?t:0;M(n),A(r),O(!0)},W=e=>{U(e.currentTarget)},G=e=>{if(!b&&z.length!==0){if(!D&&(e.key===`ArrowDown`||e.key===`Enter`||e.key===` `)){e.preventDefault(),U(e.currentTarget);return}if(D){if(e.key===`Escape`){e.preventDefault(),O(!1);return}if(e.key===`ArrowDown`){e.preventDefault(),A(e=>(e+1)%z.length);return}if(e.key===`ArrowUp`){e.preventDefault(),A(e=>e-1<0?z.length-1:e-1);return}if(e.key===`Enter`){e.preventDefault();let t=z[k];t&&H(t.id),O(!1)}}}},K={};h&&(K.placeholder=h);let q=B(L),J=(q===void 0||q===``)&&!!h,Y=L===0||B(L)===void 0;return y&&Y?``:f(u,{children:[f(t,{type:`select`,label:_,element_blok:{className:[x||``]},error:v,size:E,element_input:{className:[e.w,o.f],props:{onClick:W,onKeyDown:G,tabIndex:b?-1:0,role:`combobox`,"aria-expanded":D,"aria-haspopup":`listbox`,"aria-controls":P,...V?{"aria-activedescendant":V}:{},"aria-disabled":b?!0:void 0,"data-disabled":b?`true`:void 0}},children:[C?d(`span`,{className:e.a,children:C}):null,d(`div`,{...K,className:[e.x,J?o.p:``].filter(Boolean).join(` `),children:q??h??``}),S?d(`span`,{className:e.a,children:S}):null]}),D&&p(d(g,{parent:j||void 0,onValue:H,className:x,items:z,setOpen:O,listId:P,activeIndex:k,currentValue:L}),document.body)]})}m.displayName=`SelectField`;var h=s.memo(m),g=({onValue:e,parent:t,className:n,items:r,setOpen:s,listId:p,activeIndex:m,currentValue:h})=>{let[g]=l(()=>i());if(c(()=>()=>a(g),[g]),!t)return null;let v=()=>{s(!1)},y=t=>{s(!1),e(t)},b=Math.min(300,Math.max(52,r.length*52+8)),x=window.innerHeight-t.bottom-6-8,S=t.top-6-8,C=x<Math.min(b,160)&&S>x,w=Math.max(t.width,260),T=Math.min(Math.max(8,t.left),window.innerWidth-w-8),E=C?t.top-b-6:t.bottom+6;return E=Math.min(E,window.innerHeight-b-8),E=Math.max(8,E),f(u,{children:[d(`div`,{className:o.o,style:{zIndex:g},onClick:v,"aria-hidden":!0}),d(`div`,{className:[o.l,n].filter(e=>e!==void 0).join(` `),style:{top:`${E}px`,left:T+`px`,width:w,zIndex:g+1},children:d(_,{listId:p,items:r,link:y,activeIndex:m,currentValue:h})})]})},_=({listId:e,items:t,link:n,activeIndex:r,currentValue:i})=>d(`ul`,{id:e,role:`listbox`,children:t.map((t,a)=>d(`li`,{id:`${e}-opt-${a}`,role:`option`,"aria-selected":i===t.id,"data-focus":r===a?`true`:`false`,onClick:()=>n(t.id),children:t.label},t.id))});export{h as default};
@@ -0,0 +1,30 @@
1
+ import { ReactNode } from 'react';
2
+ import { TInput } from './type';
3
+ type TabsOptionObject = Record<string | number, {
4
+ n: string;
5
+ s?: number;
6
+ icon?: ReactNode;
7
+ }>;
8
+ type TabsOptionArrayItem = {
9
+ id?: string | number;
10
+ i?: string | number;
11
+ n: string;
12
+ /** `0` — сегмент виден, но недоступен (приглушён) */
13
+ s?: number;
14
+ /** Иконка / точка слева от подписи */
15
+ icon?: ReactNode;
16
+ };
17
+ type TabsOptions = TabsOptionObject | TabsOptionArrayItem[];
18
+ export type TTabs = TInput & {
19
+ options?: TabsOptions;
20
+ /**
21
+ * Равная ширина сегментов (по умолчанию `true`).
22
+ * `false` — ширина по содержимому.
23
+ */
24
+ equal?: boolean;
25
+ };
26
+ declare function TabsField({ value, form, onValue, onBlur: onBlurField, name, placeholder, label, error, hidden, disabled, className, after, before, options, equal, size, }: TTabs): import("react/jsx-runtime").JSX.Element | null;
27
+ declare namespace TabsField {
28
+ var displayName: string;
29
+ }
30
+ export default TabsField;
@@ -0,0 +1 @@
1
+ import e from"../styles/Field.module.js";import t from"../core/Field.js";import{useFormFieldState as n}from"../hooks/use.js";import{createFieldEmit as r}from"./emit.js";import i from"../styles/Tabs.module.js";import"react";import{jsx as a,jsxs as o}from"react/jsx-runtime";function s(e){return e?Array.isArray(e)?e.map(e=>({id:e.id??e.i??``,label:e.n||``,disabled:e.s===0,icon:e.icon})).filter(e=>e.label.length>0&&e.id!==``):Object.keys(e).map(t=>{let n=e[t],r=Number(t);return{id:Number.isFinite(r)&&String(r)===t?r:t,label:n?.n||``,disabled:n?.s===0,icon:n?.icon}}).filter(e=>e.label.length>0):[]}function c(e,t){return e===t?!0:String(e)===String(t)}function l({value:l=``,form:u,onValue:d,onBlur:f,name:p=``,placeholder:m=``,label:h=``,error:g=``,hidden:_=!1,disabled:v=!1,className:y=``,after:b=``,before:x=``,options:S,equal:C=!0,size:w}){let{value:T}=n(u,p,l),E=!v,D=s(S),O=e=>{r(u,p,d)(e,!0)};return _&&(T==null||T===``)?null:o(t,{type:`tabs`,label:h,error:g,size:w,element_blok:{className:[y||``]},element_input:{className:[i.r],props:{"data-disabled":v||!E?`true`:void 0}},children:[x?a(`span`,{className:e.a,children:x}):null,a(`div`,{className:i.i,role:`tablist`,"aria-label":h||m||`Вкладки`,style:C?void 0:{justifyContent:`flex-start`},children:D.map(e=>{let t=c(T,e.id),n=v||!E||e.disabled;return o(`button`,{type:`button`,role:`tab`,"aria-selected":t,"aria-disabled":n||void 0,disabled:n,className:[i.t,t?i.a:``].filter(Boolean).join(` `),style:C?void 0:{flex:`0 0 auto`},onClick:()=>{n||O(e.id)},onBlur:()=>{!f||!p||f({value:u?u.getValue(p,T):T,name:p})},children:[e.icon==null?null:a(`span`,{className:i.o,"aria-hidden":!0,children:e.icon}),a(`span`,{className:i.l,children:e.label})]},String(e.id))})}),b?a(`span`,{className:e.a,children:b}):null]})}l.displayName=`TabsField`;export{l as default};
@@ -1 +1 @@
1
- import e from"../styles/Field.module.js";import t from"../core/Field.js";import{useFormFieldState as n}from"../hooks/use.js";import r from"react";import{jsx as i,jsxs as a}from"react/jsx-runtime";function o(e){return Array.isArray(e)?e.map(String).map(e=>e.trim()).filter(Boolean):typeof e==`string`&&e.trim()?e.split(`,`).map(e=>e.trim()).filter(Boolean):[]}function s({value:s=[],form:c,onValue:l,onBlur:u,name:d=``,placeholder:f=`Добавить…`,label:p=``,error:m=``,hidden:h=!1,disabled:g=!1,className:_=``,after:v=``,before:y=``,maxTags:b,maxLength:x,separators:S=[`,`,`Enter`]}){let{value:C}=n(c,d,s),w=o(C),T=!g,[E,D]=r.useState(``),O=r.useRef(null),k=e=>{let t={value:e,name:d};c&&d&&c.setValue(t),l&&l!==c?.onValue&&l(t)},A=e=>{let t=e.trim();if(t&&!(x&&t.length>x)){if(w.some(e=>e.toLowerCase()===t.toLowerCase())){D(``);return}b!==void 0&&w.length>=b||(k([...w,t]),D(``))}},j=e=>{T&&k(w.filter((t,n)=>n!==e))},M=e=>{if(T){if(S.includes(e.key)||e.key===`,`&&S.includes(`,`)){e.preventDefault(),A(E);return}e.key===`Backspace`&&!E&&w.length>0&&(e.preventDefault(),j(w.length-1))}},N=w.length===0;return h&&N?null:a(t,{type:`tags`,label:p,error:m,element_blok:{className:[_||``]},element_input:{className:[e.tags],props:{"data-disabled":g||!T?`true`:void 0,onClick:()=>O.current?.focus()}},children:[y?i(`span`,{className:e.affix,children:y}):null,a(`div`,{className:e.tagsInner,children:[w.map((t,n)=>a(`span`,{className:e.tagChip,children:[i(`span`,{className:e.tagLabel,children:t}),T?i(`button`,{type:`button`,className:e.tagRemove,"aria-label":`Удалить ${t}`,onClick:e=>{e.stopPropagation(),j(n)},children:`×`}):null]},`${t}-${n}`)),T&&(b===void 0||w.length<b)?i(`input`,{ref:O,className:e.tagInput,value:E,placeholder:w.length===0?f:``,disabled:g,maxLength:x,"aria-label":p||f||`Теги`,onChange:e=>D(e.target.value),onKeyDown:M,onBlur:()=>{E.trim()&&A(E),u?.({value:w,name:d})}}):null]}),v?i(`span`,{className:e.affix,children:v}):null]})}s.displayName=`TagsField`;export{s as default};
1
+ import e from"../styles/Field.module.js";import t from"../core/Field.js";import{useFormFieldState as n}from"../hooks/use.js";import{createFieldEmit as r}from"./emit.js";import i from"../styles/Tags.module.js";import a from"react";import{jsx as o,jsxs as s}from"react/jsx-runtime";function c(e){return Array.isArray(e)?e.map(String).map(e=>e.trim()).filter(Boolean):typeof e==`string`&&e.trim()?e.split(`,`).map(e=>e.trim()).filter(Boolean):[]}function l({value:l=[],form:u,onValue:d,onBlur:f,name:p=``,placeholder:m=`Добавить…`,label:h=``,error:g=``,hidden:_=!1,disabled:v=!1,className:y=``,after:b=``,before:x=``,maxTags:S,maxLength:C,separators:w=[`,`,`Enter`]}){let{value:T}=n(u,p,l),E=c(T),D=!v,[O,k]=a.useState(``),A=a.useRef(null),j=e=>{r(u,p,d)(e,!0)},M=e=>{let t=e.trim();if(t&&!(C&&t.length>C)){if(E.some(e=>e.toLowerCase()===t.toLowerCase())){k(``);return}S!==void 0&&E.length>=S||(j([...E,t]),k(``))}},N=e=>{D&&j(E.filter((t,n)=>n!==e))},P=e=>{if(D){if(w.includes(e.key)||e.key===`,`&&w.includes(`,`)){e.preventDefault(),M(O);return}e.key===`Backspace`&&!O&&E.length>0&&(e.preventDefault(),N(E.length-1))}},F=E.length===0;return _&&F?null:s(t,{type:`tags`,label:h,error:g,element_blok:{className:[y||``]},element_input:{className:[i.r],props:{"data-disabled":v||!D?`true`:void 0,onClick:()=>A.current?.focus()}},children:[x?o(`span`,{className:e.a,children:x}):null,s(`div`,{className:i.i,children:[E.map((e,t)=>s(`span`,{className:i.c,children:[o(`span`,{className:i.l,children:e}),D?o(`button`,{type:`button`,className:i.m,"aria-label":`Удалить ${e}`,onClick:e=>{e.stopPropagation(),N(t)},children:`×`}):null]},`${e}-${t}`)),D&&(S===void 0||E.length<S)?o(`input`,{ref:A,className:i.n,value:O,placeholder:E.length===0?m:``,disabled:v,maxLength:C,"aria-label":h||m||`Теги`,onChange:e=>k(e.target.value),onKeyDown:P,onBlur:()=>{O.trim()&&M(O),f?.({value:E,name:p})}}):null]}),b?o(`span`,{className:e.a,children:b}):null]})}l.displayName=`TagsField`;export{l as default};
@@ -1 +1 @@
1
- import e from"../styles/Field.module.js";import t,{useFieldA11y as n}from"../core/Field.js";import{useFormFieldState as r}from"../hooks/use.js";import i,{asEditableClipboard as a}from"../events/onEvent.js";import{isEmptyTextLike as o}from"./visibility.js";import s from"react";import{jsx as c,jsxs as l}from"react/jsx-runtime";function u({value:n,form:u,onValue:f,name:p=``,placeholder:m=``,label:h=``,hidden:g=!1,disabled:_=!1,onBlur:v,className:y=``,after:b=``,before:x=``,error:S=``,size:C=`md`,inputmode:w=`text`,maxLength:T,spellCheck:E=!0}){let{value:D,version:O}=r(u,p||``,n),k=!_,A=String(D??``),j=s.useRef(null),M=s.useRef(!1);s.useLayoutEffect(()=>{if(M.current)return;let e=j.current;e&&e.innerText!==A&&(e.innerText=A)},[A,O]);let N=e=>{let t={value:e.currentTarget.innerText,name:p||``};u&&p&&u.onValue(t),f&&f!==u?.onValue&&f(t)},P=e=>{let t=(e.currentTarget.textContent??``).trim();T&&t.length>=T&&e.key!==`Backspace`&&e.preventDefault(),e.key===`Enter`&&!e.shiftKey&&e.preventDefault()},F=e=>i.Paste(T||0,a(e));if(g&&o(D))return null;let I={};return m&&(I.placeholder=m),k&&(I.edit=``),I.inputMode=w||`text`,l(t,{type:`note`,label:h,error:S,size:C,element_blok:{className:[y||``]},element_input:{className:[e.n]},children:[x?c(`span`,{className:e.affix,children:x}):null,c(d,{divRef:j,editable:k,label:h,placeholder:m,spellCheck:E,dd:I,onPaste:F,onInput:N,onFocus:()=>{M.current=!0},onBlur:e=>{i.Blur(e),v?.({value:(e.currentTarget.textContent??``).trim(),name:p||``}),M.current=!1},onKeyDown:P}),b?c(`span`,{className:e.affix,children:b}):null]})}function d({divRef:e,editable:t,label:r,placeholder:i,spellCheck:a,dd:o,onPaste:s,onInput:l,onFocus:u,onBlur:d,onKeyDown:f}){let p=n();return c(`div`,{ref:e,id:p?.controlId,role:`textbox`,"aria-multiline":`true`,"aria-label":r?void 0:i||`Текст`,"aria-describedby":p?.describedBy,"aria-invalid":p?.errorId?!0:void 0,tabIndex:t?0:-1,onPaste:s,onInput:l,onFocus:u,onBlur:d,onKeyDown:f,spellCheck:a,contentEditable:t?`plaintext-only`:!1,suppressContentEditableWarning:!0,...o})}u.displayName=`TextareaField`;export{u as default};
1
+ import e from"../styles/Field.module.js";import t,{useFieldA11y as n}from"../core/Field.js";import{useFormFieldState as r}from"../hooks/use.js";import{createFieldEmit as i}from"./emit.js";import a,{asEditableClipboard as o}from"../events/onEvent.js";import{isEmptyTextLike as s}from"./visibility.js";import c from"react";import{jsx as l,jsxs as u}from"react/jsx-runtime";function d({value:n,form:d,onValue:p,name:m=``,placeholder:h=``,label:g=``,hidden:_=!1,disabled:v=!1,onBlur:y,className:b=``,after:x=``,before:S=``,error:C=``,size:w=`m`,inputmode:T=`text`,maxLength:E,spellCheck:D=!0}){let{value:O,version:k}=r(d,m||``,n),A=!v,j=String(O??``),M=c.useRef(null),N=c.useRef(!1);c.useLayoutEffect(()=>{if(N.current)return;let e=M.current;e&&e.innerText!==j&&(e.innerText=j)},[j,k]);let P=i(d,m,p),F=e=>{P(e.currentTarget.innerText)},I=e=>{let t=(e.currentTarget.textContent??``).trim();E&&t.length>=E&&e.key!==`Backspace`&&e.preventDefault(),e.key===`Enter`&&!e.shiftKey&&e.preventDefault()},L=e=>a.Paste(E||0,o(e));if(_&&s(O))return null;let R={};h&&(R.placeholder=h),A&&(R.edit=``),R.inputMode=T||`text`;let z=e=>{a.Blur(e),y?.({value:(e.currentTarget.textContent??``).trim(),name:m||``}),N.current=!1},B=()=>{N.current=!0};return u(t,{type:`note`,label:g,error:C,size:w,element_blok:{className:[b||``]},element_input:{className:[e.n],props:{"data-disabled":v||!A?`true`:void 0}},children:[S?l(`span`,{className:e.a,children:S}):null,l(f,{divRef:M,editable:A,label:g,placeholder:h,spellCheck:D,dd:R,onPaste:L,onInput:F,onFocus:B,onBlur:z,onKeyDown:I}),x?l(`span`,{className:e.a,children:x}):null]})}function f({divRef:e,editable:t,label:r,placeholder:i,spellCheck:a,dd:o,onPaste:s,onInput:c,onFocus:u,onBlur:d,onKeyDown:f}){let p=n();return l(`div`,{ref:e,id:p?.controlId,role:`textbox`,"aria-multiline":`true`,"aria-label":r?void 0:i||`Текст`,"aria-describedby":p?.describedBy,"aria-invalid":p?.errorId?!0:void 0,tabIndex:t?0:-1,"aria-disabled":t?void 0:!0,onPaste:s,onInput:c,onFocus:u,onBlur:d,onKeyDown:f,spellCheck:a,contentEditable:t?`plaintext-only`:!1,suppressContentEditableWarning:!0,...o})}d.displayName=`TextareaField`;export{d as default};
@@ -1 +1 @@
1
- import e from"../styles/Field.module.js";import t from"../core/Field.js";import{useFormFieldState as n}from"../hooks/use.js";import r from"../events/onEvent.js";import{acquireOverlayZIndex as i,releaseOverlayZIndex as a}from"../overlayZ.js";import o from"../styles/Select.module.js";import s from"react";import{Fragment as c,jsx as l,jsxs as u}from"react/jsx-runtime";import{createPortal as d}from"react-dom";function f(e){let t=window.getSelection();if(!t||t.rangeCount===0)return 0;let n=t.getRangeAt(0);if(!e.contains(n.startContainer))return 0;let r=document.createRange();return r.selectNodeContents(e),r.setEnd(n.startContainer,n.startOffset),r.toString().length}function p(e,t){let n=t.firstChild;if(!n||n.nodeType!==Node.TEXT_NODE)return;let r=n.textContent?.length??0,i=Math.max(0,Math.min(e,r)),a=document.createRange(),o=window.getSelection();o&&(a.setStart(n,i),a.collapse(!0),o.removeAllRanges(),o.addRange(a),t.focus())}function m(e){return String(e).padStart(2,`0`)}function h(e){return(e||``).replace(/\D/g,``)}function g(e){if(e==null||e===``||typeof e!=`string`)return``;let t=e.trim(),n=/^(\d{1,2}):(\d{2})(?::(\d{2}))?$/.exec(t);if(!n)return``;let r=Math.min(23,Math.max(0,parseInt(n[1],10))),i=Math.min(59,Math.max(0,parseInt(n[2],10)));return`${m(r)}:${m(i)}`}function _(e){let t=g(e);if(!t)return{h:null,m:null};let[n,r]=t.split(`:`).map(e=>parseInt(e,10));return{h:n,m:r}}function v(e,t){if(e===null&&t===null)return``;let n=e??0,r=t??0;return`${m(n)}:${m(r)}`}function y(e,t){let n=h(e).slice(0,2);if(n===``)return null;let r=parseInt(n,10);return Number.isNaN(r)?null:Math.min(t,Math.max(0,r))}function b(e){let t=g(e);if(!t)return null;let[n,r]=t.split(`:`).map(e=>parseInt(e,10));return n*60+r}function x(e,t){let n=Math.max(1,Math.round(t/60));if(n<=1)return e;let r=Math.round(e/n)*n;return Math.min(59,Math.max(0,r))}function S(e,t,n){let r=g(e);if(!r)return``;let i=b(r);if(i===null)return``;if(t){let e=b(t);e!==null&&(i=Math.max(i,e))}if(n){let e=b(n);e!==null&&(i=Math.min(i,e))}return v(Math.floor(i/60),i%60)}function ee(e,t,n,r){if(r&&r.length>0){let e=new Set,i=[];for(let a of r){let r=g(a);!r||e.has(r)||(e.add(r),i.push(S(r,t,n)||r))}return i}let i=Math.max(1,Math.round(e/60));i<5&&(i=15);let a=t?b(t)??0:0,o=n?b(n)??1439:1439,s=Math.min(1439,o),c=[],l=Math.ceil(a/i)*i;for(let e=l;e<=s;e+=i){let t=Math.floor(e/60);if(t>23)break;let n=e%60;c.push(v(t,n))}return c}function te(){return u(`svg`,{viewBox:`0 0 24 24`,width:`20`,height:`20`,fill:`none`,"aria-hidden":!0,children:[l(`circle`,{cx:`12`,cy:`12`,r:`8.25`,stroke:`currentColor`,strokeWidth:`1.75`}),l(`path`,{d:`M12 7.5V12l3 2`,stroke:`currentColor`,strokeWidth:`1.75`,strokeLinecap:`round`,strokeLinejoin:`round`})]})}function C({value:i=``,form:a,onValue:o,onBlur:b,name:C=``,placeholder:re=``,label:w=``,hidden:ie=!1,disabled:T=!1,error:ae=``,className:E=``,after:D=``,before:O=``,step:k=60,min:A,max:j,id:oe,spellCheck:M=!1,align:se=`start`,picker:N=!1,presets:P}){let{value:ce,version:le}=n(a,C,i),F=g(ce),I=!T,L=s.useRef(null),R=s.useRef(null),ue=s.useRef(null),z=s.useRef(null),[B,V]=s.useState(!1),[H,U]=s.useState(!1),[W,G]=s.useState(null),[K,q]=s.useState(0),J=s.useId(),Y=s.useMemo(()=>ee(k,A,j,P),[k,A,j,P]);s.useLayoutEffect(()=>{if(!B||!I)return;let{h:e,m:t}=_(F),n=(e,t)=>{e&&(t===null?e.innerHTML=`<br>`:e.textContent=String(t))};n(L.current,e),n(R.current,t)},[B,F,le,I]);let X=s.useCallback(()=>{let e=y(L.current?.textContent||``,23),t=y(R.current?.textContent||``,59);if(e===null&&t===null)return``;let n=v(e,t);if(!n)return``;let{h:r,m:i}=_(n);return i!==null&&(n=v(r,x(i,k))),n&&=S(n,A,j),n||``},[A,j,k]),Z=s.useCallback(e=>{let t=g(e);if(t){let{h:e,m:n}=_(t);n!==null&&(t=v(e,x(n,k))),t=S(t,A,j)}return a&&C&&a.setValue({name:C,value:t}),o&&o!==a?.onValue&&o({value:t,name:C}),t},[a,C,o,A,j,k]),de=s.useCallback(()=>{if(!N||!I||Y.length===0)return;let e=z.current;if(!e)return;let t=Math.max(0,Y.findIndex(e=>e===F));q(t>=0?t:0),G(e.getBoundingClientRect()),U(!0)},[N,I,Y,F]);s.useEffect(()=>{if(!H)return;let e=()=>{let e=z.current;e&&G(e.getBoundingClientRect())};return window.addEventListener(`scroll`,e,!0),window.addEventListener(`resize`,e),()=>{window.removeEventListener(`scroll`,e,!0),window.removeEventListener(`resize`,e)}},[H]),s.useEffect(()=>{if(!H)return;let e=e=>{if(e.key===`Escape`){e.preventDefault(),U(!1);return}if(Y.length!==0){if(e.key===`ArrowDown`)e.preventDefault(),q(e=>(e+1)%Y.length);else if(e.key===`ArrowUp`)e.preventDefault(),q(e=>e-1<0?Y.length-1:e-1);else if(e.key===`Enter`){e.preventDefault();let t=Y[K];t&&(Z(t),U(!1))}}};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[H,Y,K,Z]);let Q=e=>t=>{if(t.preventDefault(),!I)return;let n=h(t.clipboardData?.getData(`text/plain`)??``),r=e===`hour`?23:59;if(n.length>=4){let e=Math.min(23,Math.max(0,parseInt(n.slice(0,2),10))),t=Math.min(59,Math.max(0,parseInt(n.slice(2,4),10))),r=L.current,i=R.current;r&&(r.textContent=String(e),queueMicrotask(()=>p(String(e).length,r))),i&&(i.textContent=String(t),queueMicrotask(()=>p(String(t).length,i)));return}let i=n.slice(0,2),a=t.currentTarget;if(i===``){a.innerHTML=`<br>`,queueMicrotask(()=>p(0,a));return}let o=parseInt(i,10);if(Number.isNaN(o))return;let s=String(Math.min(r,Math.max(0,o)));a.textContent=s,queueMicrotask(()=>p(s.length,a))},fe=e=>{let t=e.target,n=t.textContent||``,r=f(t),i=n.slice(0,r).replace(/\D/g,``).length,a=h(n).slice(0,2);if(a===``){t.innerHTML=`<br>`,queueMicrotask(()=>p(0,t));return}let o=parseInt(a,10);if(Number.isNaN(o))return;let s=String(Math.min(23,Math.max(0,o)));t.textContent=s;let c=Math.min(i,s.length);queueMicrotask(()=>p(c,t))},pe=e=>{let t=e.target,n=t.textContent||``,r=f(t),i=n.slice(0,r).replace(/\D/g,``).length,a=h(n).slice(0,2);if(a===``){t.innerHTML=`<br>`,queueMicrotask(()=>p(0,t));return}let o=parseInt(a,10);if(Number.isNaN(o))return;let s=String(Math.min(59,Math.max(0,o)));t.textContent=s;let c=Math.min(i,s.length);queueMicrotask(()=>p(c,t))},me=e=>{(e.key===`Enter`||e.key===`:`)&&(e.preventDefault(),R.current?.focus())},he=e=>{e.key===`Enter`&&e.preventDefault()},ge=e=>{let t=e.currentTarget;(t.textContent||``).trim().length||(t.innerHTML=`<br>`),I&&V(!0)},_e=e=>{r.Blur(e)};s.useEffect(()=>{let e=ue.current;if(!e)return;let t=t=>{let n=t.relatedTarget;if(n&&e.contains(n))return;let r=X();a&&C&&a.setValue({name:C,value:r}),o&&o!==a?.onValue&&o({value:r,name:C}),b&&C&&b({value:r,name:C}),V(!1)};return e.addEventListener(`focusout`,t),()=>e.removeEventListener(`focusout`,t)},[a,C,b,A,j,k,X]);let{h:ve,m:ye}=_(F),$={};I&&($.edit=``);let be={...$},xe={...$};re&&(be.placeholder=re);let Se=F!==``||B;return ie&&F===``?null:u(c,{children:[l(`div`,{ref:z,children:u(t,{type:`time`,label:w,error:ae,element_blok:{className:[E||``]},element_input:{className:[e.w,e.time,se===`center`?e.timeAlignCenter:``].filter(Boolean),props:{"data-disabled":T||!I?`true`:void 0}},children:[O?l(`span`,{className:e.affix,children:O}):null,u(`div`,{ref:ue,className:e.timeInner,role:`group`,"aria-label":w||`Время`,children:[l(`div`,{id:oe,ref:L,className:e.timePart,contentEditable:I?`plaintext-only`:!1,suppressContentEditableWarning:!0,spellCheck:M,inputMode:`numeric`,onPaste:Q(`hour`),onInput:fe,onKeyDown:me,onFocus:ge,onBlur:_e,"aria-label":`Часы, 0–23`,...be,children:!I||!B?ve===null?``:m(ve):null}),Se&&l(`span`,{className:e.timeSep,"aria-hidden":`true`,children:`:`}),l(`div`,{ref:R,className:e.timePart,contentEditable:I?`plaintext-only`:!1,suppressContentEditableWarning:!0,spellCheck:M,inputMode:`numeric`,onPaste:Q(`minute`),onInput:pe,onKeyDown:he,onFocus:ge,onBlur:_e,"aria-label":`Минуты, 0–59`,...xe,children:!I||!B?ye===null?``:m(ye):null})]}),N?l(`button`,{type:`button`,className:e.timePickerBtn,disabled:!I||Y.length===0,"aria-label":`Быстрый выбор времени`,"aria-haspopup":`listbox`,"aria-expanded":H,"aria-controls":J,onMouseDown:e=>e.preventDefault(),onClick:de,children:l(te,{})}):null,D?l(`span`,{className:e.affix,children:D}):null]})}),H&&W&&d(l(ne,{parent:W,slots:Y,current:F,activeIndex:K,listId:J,className:E,setOpen:U,setActiveIndex:q,onPick:e=>{Z(e),U(!1)}}),document.body)]})}C.displayName=`TimeField`;var ne=({parent:e,slots:t,current:n,activeIndex:r,listId:d,className:f,setOpen:p,setActiveIndex:m,onPick:h})=>{let g=s.useRef(null),[_]=s.useState(()=>i());s.useEffect(()=>()=>a(_),[_]),s.useEffect(()=>{(g.current?.querySelector(`[data-focus="true"]`))?.scrollIntoView({block:`nearest`})},[r]);let v=window.innerHeight-e.bottom<306?Math.max(6,e.top-300-6):Math.min(window.innerHeight-300-6,e.bottom+6),y=Math.max(e.width,160),b=Math.min(Math.max(6,e.left),window.innerWidth-y-6);return u(c,{children:[l(`div`,{className:o.o,style:{zIndex:_},onClick:()=>p(!1),"aria-hidden":!0}),l(`div`,{className:[o.l,f].filter(e=>e!==void 0).join(` `),style:{top:v+`px`,left:b+`px`,width:y,zIndex:_+1},children:l(`ul`,{id:d,role:`listbox`,ref:g,children:t.map((e,t)=>l(`li`,{id:`${d}-opt-${t}`,role:`option`,"aria-selected":n===e,"data-focus":r===t?`true`:`false`,onMouseEnter:()=>m(t),onClick:()=>h(e),children:e},e))})})]})};export{C as default};
1
+ import e from"../styles/Field.module.js";import t from"../core/Field.js";import{useFormFieldState as n}from"../hooks/use.js";import{createFieldEmit as r}from"./emit.js";import i from"../events/onEvent.js";import a from"../styles/Time.module.js";import o from"./TimePicker.js";import{buildTimeSlots as s,clampToRange as c,combine as l,digitsOnly as u,getRangeStartOffsetInElement as ee,normalizeTime as d,pad2 as f,parsePartDigits as p,setCursorPosition as m,snapMinute as h,splitTime as g}from"./timeUtils.js";import _ from"react";import{Fragment as te,jsx as v,jsxs as y}from"react/jsx-runtime";import{createPortal as ne}from"react-dom";function re(){return y(`svg`,{viewBox:`0 0 24 24`,width:`20`,height:`20`,fill:`none`,"aria-hidden":!0,children:[v(`circle`,{cx:`12`,cy:`12`,r:`8.25`,stroke:`currentColor`,strokeWidth:`1.75`}),v(`path`,{d:`M12 7.5V12l3 2`,stroke:`currentColor`,strokeWidth:`1.75`,strokeLinecap:`round`,strokeLinejoin:`round`})]})}function b({value:b=``,form:x,onValue:S,onBlur:C,name:w=``,placeholder:T=``,label:E=``,hidden:ie=!1,disabled:D=!1,error:ae=``,className:oe=``,after:O=``,before:k=``,step:A=60,min:j,max:M,id:se,spellCheck:N=!1,align:ce=`start`,picker:P=!1,presets:F}){let{value:le,version:ue}=n(x,w,b),I=d(le),L=!D,R=_.useRef(null),z=_.useRef(null),B=_.useRef(null),V=_.useRef(null),[H,U]=_.useState(!1),[W,G]=_.useState(!1),[K,q]=_.useState(null),[J,Y]=_.useState(0),de=_.useId(),X=_.useMemo(()=>s(A,j,M,F),[A,j,M,F]);_.useLayoutEffect(()=>{if(!H||!L)return;let{h:e,m:t}=g(I),n=(e,t)=>{e&&(t===null?e.innerHTML=`<br>`:e.textContent=String(t))};n(R.current,e),n(z.current,t)},[H,I,ue,L]);let fe=_.useCallback(()=>{let e=p(R.current?.textContent||``,23),t=p(z.current?.textContent||``,59);if(e===null&&t===null)return``;let n=l(e,t);if(!n)return``;let{h:r,m:i}=g(n);return i!==null&&(n=l(r,h(i,A))),n&&=c(n,j,M),n||``},[j,M,A]),Z=_.useCallback(e=>{let t=d(e);if(t){let{h:e,m:n}=g(t);n!==null&&(t=l(e,h(n,A))),t=c(t,j,M)}return r(x,w,S)(t,!0),t},[x,w,S,j,M,A]),pe=_.useCallback(()=>{if(!P||!L||X.length===0)return;let e=V.current;if(!e)return;let t=Math.max(0,X.findIndex(e=>e===I));Y(t>=0?t:0),q(e.getBoundingClientRect()),G(!0)},[P,L,X,I]);_.useEffect(()=>{if(!W)return;let e=()=>{let e=V.current;e&&q(e.getBoundingClientRect())};return window.addEventListener(`scroll`,e,!0),window.addEventListener(`resize`,e),()=>{window.removeEventListener(`scroll`,e,!0),window.removeEventListener(`resize`,e)}},[W]),_.useEffect(()=>{if(!W)return;let e=e=>{if(e.key===`Escape`){e.preventDefault(),G(!1);return}if(X.length!==0){if(e.key===`ArrowDown`)e.preventDefault(),Y(e=>(e+1)%X.length);else if(e.key===`ArrowUp`)e.preventDefault(),Y(e=>e-1<0?X.length-1:e-1);else if(e.key===`Enter`){e.preventDefault();let t=X[J];t&&(Z(t),G(!1))}}};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[W,X,J,Z]);let me=e=>t=>{if(t.preventDefault(),!L)return;let n=u(t.clipboardData?.getData(`text/plain`)??``),r=e===`hour`?23:59;if(n.length>=4){let e=Math.min(23,Math.max(0,parseInt(n.slice(0,2),10))),t=Math.min(59,Math.max(0,parseInt(n.slice(2,4),10))),r=R.current,i=z.current;r&&(r.textContent=String(e),queueMicrotask(()=>m(String(e).length,r))),i&&(i.textContent=String(t),queueMicrotask(()=>m(String(t).length,i)));return}let i=n.slice(0,2),a=t.currentTarget;if(i===``){a.innerHTML=`<br>`,queueMicrotask(()=>m(0,a));return}let o=parseInt(i,10);if(Number.isNaN(o))return;let s=String(Math.min(r,Math.max(0,o)));a.textContent=s,queueMicrotask(()=>m(s.length,a))},he=e=>{let t=e.target,n=t.textContent||``,r=ee(t),i=n.slice(0,r).replace(/\D/g,``).length,a=u(n).slice(0,2);if(a===``){t.innerHTML=`<br>`,queueMicrotask(()=>m(0,t));return}let o=parseInt(a,10);if(Number.isNaN(o))return;let s=String(Math.min(23,Math.max(0,o)));t.textContent=s;let c=Math.min(i,s.length);queueMicrotask(()=>m(c,t))},ge=e=>{let t=e.target,n=t.textContent||``,r=ee(t),i=n.slice(0,r).replace(/\D/g,``).length,a=u(n).slice(0,2);if(a===``){t.innerHTML=`<br>`,queueMicrotask(()=>m(0,t));return}let o=parseInt(a,10);if(Number.isNaN(o))return;let s=String(Math.min(59,Math.max(0,o)));t.textContent=s;let c=Math.min(i,s.length);queueMicrotask(()=>m(c,t))},_e=e=>{(e.key===`Enter`||e.key===`:`)&&(e.preventDefault(),z.current?.focus())},ve=e=>{e.key===`Enter`&&e.preventDefault()},ye=e=>{let t=e.currentTarget;(t.textContent||``).trim().length||(t.innerHTML=`<br>`),L&&U(!0)},be=e=>{i.Blur(e)};_.useEffect(()=>{let e=B.current;if(!e)return;let t=t=>{let n=t.relatedTarget;if(n&&e.contains(n))return;let i=fe();r(x,w,S)(i,!0),C&&w&&C({value:i,name:w}),U(!1)};return e.addEventListener(`focusout`,t),()=>e.removeEventListener(`focusout`,t)},[x,w,S,C,j,M,A,fe]);let{h:xe,m:Se}=g(I),Q={};L&&(Q.edit=``);let $={...Q},Ce={...Q};T&&($.placeholder=T);let we=I!==``||H;return ie&&I===``?null:y(te,{children:[v(`div`,{ref:V,children:y(t,{type:`time`,label:E,error:ae,element_blok:{className:[oe||``]},element_input:{className:[e.w,a.r,ce===`center`?a.c:``].filter(Boolean),props:{"data-disabled":D||!L?`true`:void 0}},children:[k?v(`span`,{className:e.a,children:k}):null,y(`div`,{ref:B,className:a.i,role:`group`,"aria-label":E||`Время`,children:[v(`div`,{id:se,ref:R,className:a.p,contentEditable:L?`plaintext-only`:!1,suppressContentEditableWarning:!0,spellCheck:N,inputMode:`numeric`,onPaste:me(`hour`),onInput:he,onKeyDown:_e,onFocus:ye,onBlur:be,"aria-label":`Часы, 0–23`,...$,children:!L||!H?xe===null?``:f(xe):null}),we&&v(`span`,{className:a.s,"aria-hidden":`true`,children:`:`}),v(`div`,{ref:z,className:a.p,contentEditable:L?`plaintext-only`:!1,suppressContentEditableWarning:!0,spellCheck:N,inputMode:`numeric`,onPaste:me(`minute`),onInput:ge,onKeyDown:ve,onFocus:ye,onBlur:be,"aria-label":`Минуты, 0–59`,...Ce,children:!L||!H?Se===null?``:f(Se):null})]}),P?v(`button`,{type:`button`,className:a.b,disabled:!L||X.length===0,"aria-label":`Быстрый выбор времени`,"aria-haspopup":`listbox`,"aria-expanded":W,"aria-controls":de,onMouseDown:e=>e.preventDefault(),onClick:pe,children:v(re,{})}):null,O?v(`span`,{className:e.a,children:O}):null]})}),W&&K&&ne(v(o,{parent:K,slots:X,current:I,activeIndex:J,listId:de,className:oe,setOpen:G,setActiveIndex:Y,onPick:e=>{Z(e),G(!1)}}),document.body)]})}b.displayName=`TimeField`;export{b as default};
@@ -0,0 +1,15 @@
1
+ import { default as React } from 'react';
2
+ export type TTimePickerProps = {
3
+ parent: DOMRect;
4
+ slots: string[];
5
+ current: string;
6
+ activeIndex: number;
7
+ listId: string;
8
+ className?: string;
9
+ setOpen: React.Dispatch<React.SetStateAction<boolean>>;
10
+ setActiveIndex: React.Dispatch<React.SetStateAction<number>>;
11
+ onPick: (slot: string) => void;
12
+ };
13
+ /** Попап со слотами времени (портал). */
14
+ declare function TimePicker({ parent, slots, current, activeIndex, listId, className, setOpen, setActiveIndex, onPick, }: TTimePickerProps): import("react/jsx-runtime").JSX.Element;
15
+ export default TimePicker;
@@ -0,0 +1 @@
1
+ import{acquireOverlayZIndex as e,releaseOverlayZIndex as t}from"../overlayZ.js";import n from"../styles/Select.module.js";import r from"react";import{Fragment as i,jsx as a,jsxs as o}from"react/jsx-runtime";function s({parent:s,slots:c,current:l,activeIndex:u,listId:d,className:f,setOpen:p,setActiveIndex:m,onPick:h}){let g=r.useRef(null),[_]=r.useState(()=>e());r.useEffect(()=>()=>t(_),[_]),r.useEffect(()=>{(g.current?.querySelector(`[data-focus="true"]`))?.scrollIntoView({block:`nearest`})},[u]);let v=window.innerHeight-s.bottom<306?s.top-300-6:s.bottom+6;v=Math.min(v,window.innerHeight-300-6),v=Math.max(6,v);let y=Math.max(s.width,160),b=Math.min(Math.max(6,s.left),window.innerWidth-y-6);return o(i,{children:[a(`div`,{className:n.o,style:{zIndex:_},onClick:()=>p(!1),"aria-hidden":!0}),a(`div`,{className:[n.l,f].filter(e=>e!==void 0).join(` `),style:{top:v+`px`,left:b+`px`,width:y,zIndex:_+1},children:a(`ul`,{id:d,role:`listbox`,ref:g,children:c.map((e,t)=>a(`li`,{id:`${d}-opt-${t}`,role:`option`,"aria-selected":l===e,"data-focus":u===t?`true`:`false`,onMouseEnter:()=>m(t),onClick:()=>h(e),children:e},e))})})]})}export{s as default};
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Алгоритм Луна для номеров банковских карт.
3
+ * @returns true, если контрольная сумма верна
4
+ */
5
+ export declare function luhnCheck(digits: string): boolean;
6
+ /** Только цифры, максимум 19 (ISO/IEC 7812) */
7
+ export declare function cardDigits(value: unknown): string;
8
+ /** Группы по 4: `4111 1111 1111 1111` */
9
+ export declare function formatCardNumber(digits: string): string;
10
+ export type CardBrand = "visa" | "mastercard" | "amex" | "mir" | "unionpay" | "unknown";
11
+ /**
12
+ * Определение платёжной системы по BIN.
13
+ * Visa / Мир / Amex — с 4 цифр. Mastercard 2xxx часто только с 6
14
+ * (диапазон 2221–2720); 2220 на четырёх — unknown.
15
+ */
16
+ export declare function detectCardBrand(digits: string): CardBrand;
17
+ /** Состояние бейджа: не пересчитываем на 5+ если уже узнали бренд. */
18
+ export type CardBrandLock = {
19
+ prefix4: string;
20
+ locked: boolean;
21
+ brand: CardBrand;
22
+ };
23
+ export declare function emptyCardBrandLock(): CardBrandLock;
24
+ /**
25
+ * Иконка по BIN:
26
+ * — меньше 4 цифр → «••••»;
27
+ * — на 4-й: Visa / Мир / Amex / MC (если хватает) — сразу и freeze;
28
+ * — если на 4 ещё unknown (часто MC 2xxx) — ждём до 6-й, потом freeze;
29
+ * — 7+ не трогаем, пока не сменятся первые 4.
30
+ */
31
+ export declare function stepCardBrand(digits: string, prev: CardBrandLock): CardBrandLock;
32
+ /**
33
+ * Проверка номера карты.
34
+ * Пустая строка — ок (обязательность снаружи).
35
+ * Неполная — ошибка; полная без Луна — ошибка.
36
+ */
37
+ export declare function validateCardNumber(value: unknown): string;
@@ -0,0 +1 @@
1
+ function e(e){let t=e.replace(/\D/g,``);if(t.length<13||t.length>19)return!1;let n=0,r=!1;for(let e=t.length-1;e>=0;e--){let i=t.charCodeAt(e)-48;if(i<0||i>9)return!1;r&&(i*=2,i>9&&(i-=9)),n+=i,r=!r}return n%10==0}function t(e){return String(e??``).replace(/\D/g,``).slice(0,19)}function n(e){return t(e).replace(/(\d{4})(?=\d)/g,`$1 `).trimEnd()}function r(e){let n=t(e);if(n.length<4)return`unknown`;let r=n.slice(0,6);return/^4/.test(r)?`visa`:/^3[47]/.test(r)?`amex`:/^220[0-4]/.test(r)?`mir`:/^(5[1-5]|222[1-9]|22[3-9]\d|2[3-6]\d{2}|27[01]\d|2720)/.test(r)?`mastercard`:/^62/.test(r)?`unionpay`:`unknown`}function i(){return{prefix4:``,locked:!1,brand:`unknown`}}function a(e,n){let o=t(e);if(o.length<4)return i();let s=o.slice(0,4);if(n.prefix4&&n.prefix4!==s)return a(o,i());if(n.locked&&n.prefix4===s)return n;let c=r(o);return c===`unknown`?o.length>=6?{prefix4:s,locked:!0,brand:`unknown`}:{prefix4:s,locked:!1,brand:`unknown`}:{prefix4:s,locked:!0,brand:c}}function o(n){let r=t(n);return r?r.length<13?`Неполный номер карты`:e(r)?``:`Некорректный номер карты`:``}export{t as cardDigits,r as detectCardBrand,i as emptyCardBrandLock,n as formatCardNumber,e as luhnCheck,a as stepCardBrand,o as validateCardNumber};
@@ -0,0 +1,29 @@
1
+ /** Встроенная палитра (6 колонок), близкая к пресетам UI */
2
+ export declare const DEFAULT_COLOR_PALETTE: string[];
3
+ export type Hsva = {
4
+ h: number;
5
+ s: number;
6
+ v: number;
7
+ a: number;
8
+ };
9
+ export declare function clamp(n: number, min: number, max: number): number;
10
+ export declare function toHexByte(n: number): string;
11
+ /** HSV → RGB 0..255 */
12
+ export declare function hsvToRgb(h: number, s: number, v: number): {
13
+ r: number;
14
+ g: number;
15
+ b: number;
16
+ };
17
+ export declare function rgbToHsv(r: number, g: number, b: number): Omit<Hsva, "a">;
18
+ /** #RGB / #RRGGBB / #RRGGBBAA → hsva */
19
+ export declare function parseHexColor(input: unknown): Hsva | null;
20
+ /** hsva → #RRGGBB или #RRGGBBAA (alpha &lt; 1) */
21
+ export declare function formatHexColor(hsva: Hsva, withAlpha: boolean): string;
22
+ export declare function cssColor(hsva: Hsva): string;
23
+ export declare function hueCss(h: number): string;
24
+ export declare function normalizeHexCompare(hex: string): string;
25
+ export declare function isEmptyColor(value: unknown): boolean;
26
+ export declare function isEditablePasteTarget(target: EventTarget | null): boolean;
27
+ /** Hex / rgb из буфера обмена */
28
+ export declare function parseClipboardColor(text: string): Hsva | null;
29
+ export declare function hasEyeDropper(): boolean;
@@ -0,0 +1 @@
1
+ var e=`#FF2D55.#FF3B30.#FF453A.#FF6961.#FF8A80.#C11F3E.#AF52DE.#BF5AF2.#DA8FFF.#5856D6.#5E5CE6.#7D7AFF.#007AFF.#0A84FF.#409CFF.#64D2FF.#70D7FF.#5AC8FA.#32ADE6.#64D2FF.#40C8E0.#00C7BE.#63E6E2.#66D4CF.#34C759.#30D158.#30DB5B.#4CD964.#6DE6A0.#8EEDB3.#A8E10C.#B5F200.#D0FF00.#E4FF66.#F2FF99.#C6FF00.#FFCC00.#FFD60A.#FFEA00.#FFE066.#FFF3A3.#FFEB3B.#FF9500.#FF9F0A.#FFB340.#FFB340.#FFD580.#FF8C00.#A2845E.#AC8E68.#C4A484.#8E8E93.#636366.#48484A.#3A3A3C.#2C2C2E.#1C1C1E`.split(`.`);function t(e,t,n){return Math.min(n,Math.max(t,e))}function n(e){return Math.round(t(e,0,255)).toString(16).padStart(2,`0`).toUpperCase()}function r(e,t,n){let r=(e%360+360)%360,i=n*t,a=i*(1-Math.abs(r/60%2-1)),o=n-i,s=0,c=0,l=0;return r<60?[s,c,l]=[i,a,0]:r<120?[s,c,l]=[a,i,0]:r<180?[s,c,l]=[0,i,a]:r<240?[s,c,l]=[0,a,i]:r<300?[s,c,l]=[a,0,i]:[s,c,l]=[i,0,a],{r:(s+o)*255,g:(c+o)*255,b:(l+o)*255}}function i(e,t,n){let r=e/255,i=t/255,a=n/255,o=Math.max(r,i,a),s=o-Math.min(r,i,a),c=0;s!==0&&(c=o===r?(i-a)/s%6:o===i?(a-r)/s+2:(r-i)/s+4,c*=60,c<0&&(c+=360));let l=o===0?0:s/o;return{h:c,s:l,v:o}}function a(e){if(typeof e!=`string`)return null;let t=e.trim();if(!t||(t[0]===`#`&&(t=t.slice(1)),![3,4,6,8].includes(t.length))||!/^[0-9a-fA-F]+$/.test(t))return null;let n=0,r=0,a=0,o=1;return t.length===3||t.length===4?(n=parseInt(t[0]+t[0],16),r=parseInt(t[1]+t[1],16),a=parseInt(t[2]+t[2],16),t.length===4&&(o=parseInt(t[3]+t[3],16)/255)):(n=parseInt(t.slice(0,2),16),r=parseInt(t.slice(2,4),16),a=parseInt(t.slice(4,6),16),t.length===8&&(o=parseInt(t.slice(6,8),16)/255)),{...i(n,r,a),a:o}}function o(e,t){let{r:i,g:a,b:o}=r(e.h,e.s,e.v),s=`#${n(i)}${n(a)}${n(o)}`;return!t||e.a>=.999?s:`${s}${n(e.a*255)}`}function s(e){let{r:t,g:n,b:i}=r(e.h,e.s,e.v),a=Math.round(t),o=Math.round(n),s=Math.round(i);return e.a>=.999?`rgb(${a}, ${o}, ${s})`:`rgba(${a}, ${o}, ${s}, ${Number(e.a.toFixed(3))})`}function c(e){let{r:t,g:n,b:i}=r(e,1,1);return`rgb(${Math.round(t)},${Math.round(n)},${Math.round(i)})`}function l(e){let t=a(e);return t?o(t,t.a<.999):e.toUpperCase()}function u(e){return e==null?!0:typeof e==`string`?e.trim()===``:!1}function d(e){if(!(e instanceof HTMLElement))return!1;let t=e.tagName;return t===`INPUT`||t===`TEXTAREA`||t===`SELECT`?!0:!!e.isContentEditable}function f(e){let n=(e||``).trim();if(!n)return null;let r=a(n)??a(n[0]===`#`?n:`#${n.replace(/^#/,``)}`);if(r)return r;let o=/^rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})(?:\s*,\s*([\d.]+))?\s*\)$/i.exec(n);if(o){let e=t(Number(o[1]),0,255),n=t(Number(o[2]),0,255),r=t(Number(o[3]),0,255),a=o[4]===void 0?1:t(Number(o[4]),0,1);return{...i(e,n,r),a}}return null}function p(){return typeof window<`u`&&`EyeDropper`in window}export{e as DEFAULT_COLOR_PALETTE,t as clamp,s as cssColor,o as formatHexColor,p as hasEyeDropper,c as hueCss,d as isEditablePasteTarget,u as isEmptyColor,l as normalizeHexCompare,f as parseClipboardColor,a as parseHexColor};
@@ -0,0 +1,32 @@
1
+ export type TDateTemplate = "dd.mm.yyyy" | "yyyy-mm-dd" | "dd.mm.yy" | "dd.mm.yyyy HH:MM:SS" | string;
2
+ export type TDatePosition = {
3
+ x: number;
4
+ y: number;
5
+ b: number;
6
+ };
7
+ export type TMonthInfo = {
8
+ val: string;
9
+ name: string;
10
+ names: string;
11
+ abc: string;
12
+ };
13
+ /** Для отображения в триггере: пусто → placeholder/data-placeholder, не «сегодня» */
14
+ export declare function isDateDisplayEmpty(value: unknown): boolean;
15
+ /** Месяц (1–12) в году y попадает в диапазон min/max */
16
+ export declare function isMonthInRange(y: number, m: number, min?: Date, max?: Date): boolean;
17
+ /** Год целиком пересекается с min/max */
18
+ export declare function isYearInRange(y: number, min?: Date, max?: Date): boolean;
19
+ /** Начало 12-летнего блока для сетки лет, с учётом min/max */
20
+ export declare function clampYearPageStart(start: number, min?: Date, max?: Date): number;
21
+ export declare function isEditablePasteTarget(target: EventTarget | null): boolean;
22
+ /** Разбор даты из буфера: dd.mm.yyyy, yyyy-mm-dd и т.п. */
23
+ export declare function parseClipboardDate(text: string): Date | null;
24
+ export declare function clampDateValue(d: Date, min?: Date, max?: Date): Date;
25
+ /** Дополнение числа ведущими нулями до длины l */
26
+ export declare function FormatNumber(l: number, n: number): string;
27
+ /** Дата в формате хранения формы: YYYY-MM-DD */
28
+ export declare function toStoreDateString(d: Date): string;
29
+ /** Имя месяца (1–12) или из Date */
30
+ export declare function FormatMonth(m: number | Date): TMonthInfo;
31
+ /** Форматирование даты по шаблону (dd.mm.yyyy и т.п.) */
32
+ export declare function FormatDate(x: Date | string | number, y?: TDateTemplate): string;
@@ -0,0 +1 @@
1
+ import{isEmptyTextLike as e}from"./visibility.js";function t(t){return!!(t==null||typeof t==`string`&&e(t)||t instanceof Date&&Number.isNaN(t.getTime()))}function n(e,t,n,r){let i=new Date(e,t-1,1);return!(n&&new Date(e,t,0)<n||r&&i>r)}function r(e,t,n){return!(t&&e<t.getFullYear()||n&&e>n.getFullYear())}function i(e,t,n){let r=e;if(t){let e=t.getFullYear();r+11<e&&(r=e-11),r<e&&(r=e)}if(n){let e=n.getFullYear();r>e&&(r=e-11),r+11>e&&(r=e-11)}return r}function a(e){if(!(e instanceof HTMLElement))return!1;let t=e.tagName;return t===`INPUT`||t===`TEXTAREA`||t===`SELECT`?!0:!!e.isContentEditable}function o(e){let t=(e||``).trim();if(!t)return null;let n=t.split(/\s+/)[0].replace(/,/g,`.`),r=(e,t,n)=>{if(t<1||t>12||n<1||n>31)return null;let r=e<100?2e3+e:e,i=new Date(r,t-1,n);return Number.isNaN(i.getTime())||i.getFullYear()!==r||i.getMonth()!==t-1||i.getDate()!==n?null:i},i=/^(\d{1,2})[./](\d{1,2})[./](\d{2,4})$/.exec(n);if(i)return r(parseInt(i[3],10),parseInt(i[2],10),parseInt(i[1],10));if(i=/^(\d{4})-(\d{1,2})-(\d{1,2})$/.exec(n),i)return r(parseInt(i[1],10),parseInt(i[2],10),parseInt(i[3],10));if(i=/^(\d{1,2})\/(\d{1,2})\/(\d{2,4})$/.exec(n),i)return r(parseInt(i[3],10),parseInt(i[2],10),parseInt(i[1],10));let a=n.replace(/\D/g,``);return a.length===8?r(parseInt(a.slice(4,8),10),parseInt(a.slice(2,4),10),parseInt(a.slice(0,2),10))||r(parseInt(a.slice(0,4),10),parseInt(a.slice(4,6),10),parseInt(a.slice(6,8),10)):null}function s(e,t,n){let r=e.getTime();return t&&r<t.getTime()&&(r=t.getTime()),n&&r>n.getTime()&&(r=n.getTime()),new Date(r)}function c(e,t){let n=t+``;for(;n.length<e;)n=`0`+n;return n}function l(e){return e.getFullYear()+`-`+c(2,e.getMonth()+1)+`-`+c(2,e.getDate())}var u={val:`01`,name:`—`,names:`—`,abc:`—`};function d(e){let t=typeof e==`number`?e:new Date(e).getMonth()+1;return(!Number.isFinite(t)||t<1||t>12)&&(t=new Date().getMonth()+1),{1:{val:`01`,name:`Январь`,names:`Января`,abc:`Янв`},2:{val:`02`,name:`Февраль`,names:`Февраля`,abc:`Февр`},3:{val:`03`,name:`Март`,names:`Марта`,abc:`Март`},4:{val:`04`,name:`Апрель`,names:`Апреля`,abc:`Апр`},5:{val:`05`,name:`Май`,names:`Мая`,abc:`Май`},6:{val:`06`,name:`Июнь`,names:`Июня`,abc:`Июнь`},7:{val:`07`,name:`Июль`,names:`Июля`,abc:`Июль`},8:{val:`08`,name:`Август`,names:`Августа`,abc:`Авг`},9:{val:`09`,name:`Сентябрь`,names:`Сентября`,abc:`Сент`},10:{val:`10`,name:`Октябрь`,names:`Октября`,abc:`Окт`},11:{val:`11`,name:`Ноябрь`,names:`Ноября`,abc:`Нояб`},12:{val:`12`,name:`Декабрь`,names:`Декабря`,abc:`Дек`}}[t]??u}function f(e,t){let n,r;t===void 0?(r=String(e),n=new Date):(r=t,n=new Date(e)),Number.isNaN(n.getTime())&&(n=new Date);let i=r,a={yyyy:n.getFullYear(),yy:(``+n.getFullYear()).slice(-2),mm:(`0`+(n.getMonth()+1)).slice(-2),dd:(`0`+n.getDate()).slice(-2),HH:(`0`+n.getHours()).slice(-2),MM:(`0`+n.getMinutes()).slice(-2),SS:(`0`+n.getSeconds()).slice(-2),__:` \xA0\xA0\xA0\xA0 `,_:` \xA0\xA0 `};for(let e in a)i=i.replace(e,String(a[e]));return i}export{f as FormatDate,d as FormatMonth,c as FormatNumber,s as clampDateValue,i as clampYearPageStart,t as isDateDisplayEmpty,a as isEditablePasteTarget,n as isMonthInRange,r as isYearInRange,o as parseClipboardDate,l as toStoreDateString};
@@ -0,0 +1,4 @@
1
+ /** Практичная проверка email (не полный RFC). Пустая строка — ок. */
2
+ export declare function isValidEmail(value: unknown): boolean;
3
+ /** Текст ошибки или "" */
4
+ export declare function validateEmail(value: unknown): string;
@@ -0,0 +1 @@
1
+ function e(e){let t=String(e??``).trim();return t?/^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/i.test(t):!0}function t(t){let n=String(t??``).trim();return n?e(n)?``:`Некорректный email`:``}export{e as isValidEmail,t as validateEmail};
@@ -0,0 +1,23 @@
1
+ /** Смещение начала выделения в символах от начала contentEditable (как в Mask.tsx) */
2
+ export declare function getRangeStartOffsetInElement(el: HTMLElement): number;
3
+ /** Установка каретки в позицию `pos` (символы), как в Mask.tsx */
4
+ export declare function setCursorPosition(pos: number, elem: HTMLElement): void;
5
+ export declare function pad2(n: number): string;
6
+ export declare function digitsOnly(s: string): string;
7
+ export declare function normalizeTime(v: unknown): string;
8
+ export declare function splitTime(s: string): {
9
+ h: number | null;
10
+ m: number | null;
11
+ };
12
+ /** Сборка `HH:mm` с ведущими нулями — только при коммите (blur), не во время ввода */
13
+ export declare function combine(h: number | null, m: number | null): string;
14
+ /** Цифры из текста части (часы/минуты) в DOM */
15
+ export declare function parsePartDigits(s: string, max: number): number | null;
16
+ export declare function toMinutes(hhmm: string): number | null;
17
+ export declare function snapMinute(minute: number, stepSec: number): number;
18
+ export declare function clampToRange(hhmm: string, min?: string, max?: string): string;
19
+ /**
20
+ * Слоты для popup. При step меньше 5 мин список слишком длинный —
21
+ * для picker берём минимум 15 мин, если нет явных `presets`.
22
+ */
23
+ export declare function buildTimeSlots(stepSec: number, min?: string, max?: string, presets?: string[]): string[];
@@ -0,0 +1 @@
1
+ function e(e){let t=window.getSelection();if(!t||t.rangeCount===0)return 0;let n=t.getRangeAt(0);if(!e.contains(n.startContainer))return 0;let r=document.createRange();return r.selectNodeContents(e),r.setEnd(n.startContainer,n.startOffset),r.toString().length}function t(e,t){let n=t.firstChild;if(!n||n.nodeType!==Node.TEXT_NODE)return;let r=n.textContent?.length??0,i=Math.max(0,Math.min(e,r)),a=document.createRange(),o=window.getSelection();o&&(a.setStart(n,i),a.collapse(!0),o.removeAllRanges(),o.addRange(a),t.focus())}function n(e){return String(e).padStart(2,`0`)}function r(e){return(e||``).replace(/\D/g,``)}function i(e){if(e==null||e===``||typeof e!=`string`)return``;let t=e.trim(),r=/^(\d{1,2}):(\d{2})(?::(\d{2}))?$/.exec(t);if(!r)return``;let i=Math.min(23,Math.max(0,parseInt(r[1],10))),a=Math.min(59,Math.max(0,parseInt(r[2],10)));return`${n(i)}:${n(a)}`}function a(e){let t=i(e);if(!t)return{h:null,m:null};let[n,r]=t.split(`:`).map(e=>parseInt(e,10));return{h:n,m:r}}function o(e,t){if(e===null&&t===null)return``;let r=e??0,i=t??0;return`${n(r)}:${n(i)}`}function s(e,t){let n=r(e).slice(0,2);if(n===``)return null;let i=parseInt(n,10);return Number.isNaN(i)?null:Math.min(t,Math.max(0,i))}function c(e){let t=i(e);if(!t)return null;let[n,r]=t.split(`:`).map(e=>parseInt(e,10));return n*60+r}function l(e,t){let n=Math.max(1,Math.round(t/60));if(n<=1)return e;let r=Math.round(e/n)*n;return Math.min(59,Math.max(0,r))}function u(e,t,n){let r=i(e);if(!r)return``;let a=c(r);if(a===null)return``;if(t){let e=c(t);e!==null&&(a=Math.max(a,e))}if(n){let e=c(n);e!==null&&(a=Math.min(a,e))}return o(Math.floor(a/60),a%60)}function d(e,t,n,r){if(r&&r.length>0){let e=new Set,a=[];for(let o of r){let r=i(o);!r||e.has(r)||(e.add(r),a.push(u(r,t,n)||r))}return a}let a=Math.max(1,Math.round(e/60));a<5&&(a=15);let s=t?c(t)??0:0,l=n?c(n)??1439:1439,d=Math.min(1439,l),f=[],p=Math.ceil(s/a)*a;for(let e=p;e<=d;e+=a){let t=Math.floor(e/60);if(t>23)break;let n=e%60;f.push(o(t,n))}return f}export{d as buildTimeSlots,u as clampToRange,o as combine,r as digitsOnly,e as getRangeStartOffsetInElement,i as normalizeTime,n as pad2,s as parsePartDigits,t as setCursorPosition,l as snapMinute,a as splitTime};
@@ -28,10 +28,11 @@ export type TFieldPresentation = {
28
28
  id?: string;
29
29
  className?: string;
30
30
  /**
31
- * Плотность поля: `md` — формы/модалки (по умолчанию),
32
- * `sm` тулбары и плотные модалки.
31
+ * Высота: `"s"` | `"m"` | `"l"` как у кнопки и поиска.
32
+ * Единая шкала с button/search: `"s"` | `"m"` | `"l"`.
33
+ * `"sm"` / `"md"` — устаревшие алиасы (`elcrm migrate size-sml`).
33
34
  */
34
- size?: "sm" | "md";
35
+ size?: "s" | "m" | "l" | "sm" | "md";
35
36
  isCopy?: boolean;
36
37
  maxLength?: number;
37
38
  /**
@@ -6,16 +6,16 @@ type FormChange = {
6
6
  value?: unknown;
7
7
  };
8
8
  type Listener = () => void;
9
- export type UseFormApi = {
10
- valuesRef: React.MutableRefObject<FormValues>;
9
+ export type UseFormApi<T extends FormValues = FormValues> = {
10
+ valuesRef: React.MutableRefObject<T>;
11
11
  onValue: (payload: FormChange) => void;
12
12
  setValue: (payload: FormChange) => void;
13
- setValues: (nextValues: FormValues) => void;
13
+ setValues: (nextValues: Partial<T> & FormValues) => void;
14
14
  /** Неглубокая копия текущих значений (защита от случайной мутации снаружи) */
15
- getValues: () => FormValues;
16
- getValue: (name: string, fallback?: unknown) => unknown;
15
+ getValues: () => T;
16
+ getValue: <K extends string>(name: K, fallback?: unknown) => K extends keyof T ? T[K] : unknown;
17
17
  getVersion: (name: string) => number;
18
- reset: (nextValues?: FormValues) => void;
18
+ reset: (nextValues?: T) => void;
19
19
  subscribe: (name: string, listener: Listener) => () => void;
20
20
  };
21
21
  /**
@@ -24,8 +24,13 @@ export type UseFormApi = {
24
24
  * Чтение: form.getValue("name"), form.getValues()
25
25
  * Запись без ререндера: form.onValue({ name, value })
26
26
  * Запись с уведомлением подписчиков поля: form.setValue({ name, value })
27
+ *
28
+ * @example
29
+ * type Values = { login: string; role: number };
30
+ * const form = useForm<Values>({ login: "", role: 0 });
31
+ * form.getValues().login; // string
27
32
  */
28
- export declare function useForm(initialValues?: FormValues): UseFormApi;
33
+ export declare function useForm<T extends FormValues = FormValues>(initialValues?: T): UseFormApi<T>;
29
34
  /**
30
35
  * Подписка на одно поле формы: актуальное значение + версия (для key у contentEditable и т.п.).
31
36
  * Поля используют внутри себя; снаружи обычно достаточно передать form + name.