denwa-react-shared 1.0.87 → 1.0.89
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/denwa-react-shared.cjs.js +1 -1
- package/dist/denwa-react-shared.es.js +1 -1
- package/dist/denwa-react-shared.umd.js +1 -1
- package/dist/{index-B2LJV9hD.js → index-B9Fobz_H.js} +1 -1
- package/dist/{index-Dm99lN_c.cjs → index-DFjIWZK2.cjs} +1 -1
- package/dist/{index-BsL--dhU.js → index-DQufMkbF.js} +1853 -1856
- package/dist/{index-UAPQw7y7.cjs → index-n5OyW3Ln.cjs} +57 -57
- package/dist/{table-head-V4MoUZSY.js → table-head-Dhg7yOFA.js} +1 -1
- package/dist/{table-head-ByE_XMtl.cjs → table-head-Tj5W8nwu.cjs} +1 -1
- package/package.json +11 -2
- package/skills/admin-forms/SKILL.md +121 -0
- package/skills/admin-table/SKILL.md +153 -0
- package/skills/material-map/SKILL.md +65 -0
- package/skills/media-management/SKILL.md +107 -0
- package/skills/session-auth/SKILL.md +100 -0
- package/skills/text-editor/SKILL.md +100 -0
- package/skills/utility-hooks/SKILL.md +97 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { _ as F, u as Ce, C as Re, a as G, c as X, b as de, d as je, e as Oe, o as Ne, f as ie, g as L, h as ue, i as Me, m as Ee, r as Ie, j as He, k as B, l as Pe, t as Ve, n as De, p as Be, q as Te, I as Ae, s as _e, v as ze, w as Fe, x as Ke, T as Le, y as v, F as U, z as W, S as Z, B as We, A as Xe, D as qe, E as Ue, G as J, H as oe, R as Ge } from "./index-
|
|
1
|
+
import { _ as F, u as Ce, C as Re, a as G, c as X, b as de, d as je, e as Oe, o as Ne, f as ie, g as L, h as ue, i as Me, m as Ee, r as Ie, j as He, k as B, l as Pe, t as Ve, n as De, p as Be, q as Te, I as Ae, s as _e, v as ze, w as Fe, x as Ke, T as Le, y as v, F as U, z as W, S as Z, B as We, A as Xe, D as qe, E as Ue, G as J, H as oe, R as Ge } from "./index-DQufMkbF.js";
|
|
2
2
|
import * as i from "react";
|
|
3
3
|
import { useState as Ye, useMemo as Je, createElement as Ze } from "react";
|
|
4
4
|
var le = function(t, n) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("./index-UAPQw7y7.cjs"),K=require("react");function me(e){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e){for(const i in e)if(i!=="default"){const a=Object.getOwnPropertyDescriptor(e,i);Object.defineProperty(t,i,a.get?a:{enumerable:!0,get:()=>e[i]})}}return t.default=e,Object.freeze(t)}const o=me(K);var J=function(t,i){if(!t)return null;var a={left:t.offsetLeft,right:t.parentElement.clientWidth-t.clientWidth-t.offsetLeft,width:t.clientWidth,top:t.offsetTop,bottom:t.parentElement.clientHeight-t.clientHeight-t.offsetTop,height:t.clientHeight};return i?{left:0,right:0,width:0,top:a.top,bottom:a.bottom,height:a.height}:{left:a.left,right:a.right,width:a.width,top:0,bottom:0,height:0}},T=function(t){return t!==void 0?"".concat(t,"px"):void 0};function fe(e){var t=e.prefixCls,i=e.containerRef,a=e.value,r=e.getValueIndex,s=e.motionName,p=e.onMotionStart,h=e.onMotionEnd,b=e.direction,S=e.vertical,d=S===void 0?!1:S,$=o.useRef(null),w=o.useState(a),R=n._slicedToArray(w,2),v=R[0],M=R[1],C=function(P){var m,B=r(P),_=(m=i.current)===null||m===void 0?void 0:m.querySelectorAll(".".concat(t,"-item"))[B];return(_==null?void 0:_.offsetParent)&&_},E=o.useState(null),f=n._slicedToArray(E,2),l=f[0],N=f[1],V=o.useState(null),x=n._slicedToArray(V,2),c=x[0],I=x[1];n.useLayoutEffect(function(){if(v!==a){var u=C(v),P=C(a),m=J(u,d),B=J(P,d);M(a),N(m),I(B),u&&P?p():h()}},[a]);var y=o.useMemo(function(){if(d){var u;return T((u=l==null?void 0:l.top)!==null&&u!==void 0?u:0)}return T(b==="rtl"?-(l==null?void 0:l.right):l==null?void 0:l.left)},[d,b,l]),O=o.useMemo(function(){if(d){var u;return T((u=c==null?void 0:c.top)!==null&&u!==void 0?u:0)}return T(b==="rtl"?-(c==null?void 0:c.right):c==null?void 0:c.left)},[d,b,c]),D=function(){return d?{transform:"translateY(var(--thumb-start-top))",height:"var(--thumb-start-height)"}:{transform:"translateX(var(--thumb-start-left))",width:"var(--thumb-start-width)"}},H=function(){return d?{transform:"translateY(var(--thumb-active-top))",height:"var(--thumb-active-height)"}:{transform:"translateX(var(--thumb-active-left))",width:"var(--thumb-active-width)"}},A=function(){N(null),I(null),h()};return!l||!c?null:o.createElement(n.CSSMotion,{visible:!0,motionName:s,motionAppear:!0,onAppearStart:D,onAppearActive:H,onVisibleChanged:A},function(u,P){var m=u.className,B=u.style,_=n._objectSpread2(n._objectSpread2({},B),{},{"--thumb-start-left":y,"--thumb-start-width":T(l==null?void 0:l.width),"--thumb-active-left":O,"--thumb-active-width":T(c==null?void 0:c.width),"--thumb-start-top":y,"--thumb-start-height":T(l==null?void 0:l.height),"--thumb-active-top":O,"--thumb-active-height":T(c==null?void 0:c.height)}),F={ref:n.composeRef($,P),style:_,className:n.cn("".concat(t,"-thumb"),m)};return process.env.NODE_ENV==="test"&&(F["data-test-style"]=JSON.stringify(_)),o.createElement("div",F)})}var ve=["prefixCls","direction","vertical","options","disabled","defaultValue","value","name","onChange","className","motionName"];function ge(e){if(typeof e.title<"u")return e.title;if(n._typeof(e.label)!=="object"){var t;return(t=e.label)===null||t===void 0?void 0:t.toString()}}function he(e){return e.map(function(t){if(n._typeof(t)==="object"&&t!==null){var i=ge(t);return n._objectSpread2(n._objectSpread2({},t),{},{title:i})}return{label:t==null?void 0:t.toString(),title:t==null?void 0:t.toString(),value:t}})}var be=function(t){var i=t.prefixCls,a=t.className,r=t.disabled,s=t.checked,p=t.label,h=t.title,b=t.value,S=t.name,d=t.onChange,$=t.onFocus,w=t.onBlur,R=t.onKeyDown,v=t.onKeyUp,M=t.onMouseDown,C=function(f){r||d(f,b)};return o.createElement("label",{className:n.cn(a,n._defineProperty({},"".concat(i,"-item-disabled"),r)),onMouseDown:M},o.createElement("input",{name:S,className:"".concat(i,"-item-input"),type:"radio",disabled:r,checked:s,onChange:C,onFocus:$,onBlur:w,onKeyDown:R,onKeyUp:v}),o.createElement("div",{className:"".concat(i,"-item-label"),title:h,"aria-selected":s},p))},ee=o.forwardRef(function(e,t){var i,a,r=e.prefixCls,s=r===void 0?"rc-segmented":r,p=e.direction,h=e.vertical,b=e.options,S=b===void 0?[]:b,d=e.disabled,$=e.defaultValue,w=e.value,R=e.name,v=e.onChange,M=e.className,C=M===void 0?"":M,E=e.motionName,f=E===void 0?"thumb-motion":E,l=n._objectWithoutProperties(e,ve),N=o.useRef(null),V=o.useMemo(function(){return n.composeRef(N,t)},[N,t]),x=o.useMemo(function(){return he(S)},[S]),c=n.useMergedState((i=x[0])===null||i===void 0?void 0:i.value,{value:w,defaultValue:$}),I=n._slicedToArray(c,2),y=I[0],O=I[1],D=o.useState(!1),H=n._slicedToArray(D,2),A=H[0],u=H[1],P=function(j,z){O(z),v==null||v(z)},m=n.omit(l,["children"]),B=o.useState(!1),_=n._slicedToArray(B,2),F=_[0],X=_[1],ae=o.useState(!1),q=n._slicedToArray(ae,2),ie=q[0],U=q[1],oe=function(){U(!0)},re=function(){U(!1)},le=function(){X(!1)},se=function(j){j.key==="Tab"&&X(!0)},G=function(j){var z=x.findIndex(function(de){return de.value===y}),Y=x.length,ue=(z+j+Y)%Y,L=x[ue];L&&(O(L.value),v==null||v(L.value))},ce=function(j){switch(j.key){case"ArrowLeft":case"ArrowUp":G(-1);break;case"ArrowRight":case"ArrowDown":G(1);break}};return o.createElement("div",n._extends({role:"radiogroup","aria-label":"segmented control",tabIndex:d?void 0:0},m,{className:n.cn(s,(a={},n._defineProperty(a,"".concat(s,"-rtl"),p==="rtl"),n._defineProperty(a,"".concat(s,"-disabled"),d),n._defineProperty(a,"".concat(s,"-vertical"),h),a),C),ref:V}),o.createElement("div",{className:"".concat(s,"-group")},o.createElement(fe,{vertical:h,prefixCls:s,value:y,containerRef:N,motionName:"".concat(s,"-").concat(f),direction:p,getValueIndex:function(j){return x.findIndex(function(z){return z.value===j})},onMotionStart:function(){u(!0)},onMotionEnd:function(){u(!1)}}),x.map(function(g){var j;return o.createElement(be,n._extends({},g,{name:R,key:g.value,prefixCls:s,className:n.cn(g.className,"".concat(s,"-item"),(j={},n._defineProperty(j,"".concat(s,"-item-selected"),g.value===y&&!A),n._defineProperty(j,"".concat(s,"-item-focused"),ie&&F&&g.value===y),j)),checked:g.value===y,onChange:P,onFocus:oe,onBlur:re,onKeyDown:ce,onKeyUp:se,onMouseDown:le,disabled:!!d||!!g.disabled}))})))});process.env.NODE_ENV!=="production"&&(ee.displayName="Segmented");var pe=ee;function Z(e,t){return{[`${e}, ${e}:hover, ${e}:focus`]:{color:t.colorTextDisabled,cursor:"not-allowed"}}}function Q(e){return{backgroundColor:e.itemSelectedBg,boxShadow:e.boxShadowTertiary}}const xe=Object.assign({overflow:"hidden"},n.textEllipsis),Se=e=>{const{componentCls:t}=e,i=e.calc(e.controlHeight).sub(e.calc(e.trackPadding).mul(2)).equal(),a=e.calc(e.controlHeightLG).sub(e.calc(e.trackPadding).mul(2)).equal(),r=e.calc(e.controlHeightSM).sub(e.calc(e.trackPadding).mul(2)).equal();return{[t]:Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},n.resetComponent(e)),{display:"inline-block",padding:e.trackPadding,color:e.itemColor,background:e.trackBg,borderRadius:e.borderRadius,transition:`all ${e.motionDurationMid} ${e.motionEaseInOut}`}),n.genFocusStyle(e)),{[`${t}-group`]:{position:"relative",display:"flex",alignItems:"stretch",justifyItems:"flex-start",flexDirection:"row",width:"100%"},[`&${t}-rtl`]:{direction:"rtl"},[`&${t}-vertical`]:{[`${t}-group`]:{flexDirection:"column"},[`${t}-thumb`]:{width:"100%",height:0,padding:`0 ${n.unit(e.paddingXXS)}`}},[`&${t}-block`]:{display:"flex"},[`&${t}-block ${t}-item`]:{flex:1,minWidth:0},[`${t}-item`]:{position:"relative",textAlign:"center",cursor:"pointer",transition:`color ${e.motionDurationMid} ${e.motionEaseInOut}`,borderRadius:e.borderRadiusSM,transform:"translateZ(0)","&-selected":Object.assign(Object.assign({},Q(e)),{color:e.itemSelectedColor}),"&-focused":Object.assign({},n.genFocusOutline(e)),"&::after":{content:'""',position:"absolute",zIndex:-1,width:"100%",height:"100%",top:0,insetInlineStart:0,borderRadius:"inherit",opacity:0,transition:`opacity ${e.motionDurationMid}`,pointerEvents:"none"},[`&:hover:not(${t}-item-selected):not(${t}-item-disabled)`]:{color:e.itemHoverColor,"&::after":{opacity:1,backgroundColor:e.itemHoverBg}},[`&:active:not(${t}-item-selected):not(${t}-item-disabled)`]:{color:e.itemHoverColor,"&::after":{opacity:1,backgroundColor:e.itemActiveBg}},"&-label":Object.assign({minHeight:i,lineHeight:n.unit(i),padding:`0 ${n.unit(e.segmentedPaddingHorizontal)}`},xe),"&-icon + *":{marginInlineStart:e.calc(e.marginSM).div(2).equal()},"&-input":{position:"absolute",insetBlockStart:0,insetInlineStart:0,width:0,height:0,opacity:0,pointerEvents:"none"}},[`${t}-thumb`]:Object.assign(Object.assign({},Q(e)),{position:"absolute",insetBlockStart:0,insetInlineStart:0,width:0,height:"100%",padding:`${n.unit(e.paddingXXS)} 0`,borderRadius:e.borderRadiusSM,transition:`transform ${e.motionDurationSlow} ${e.motionEaseInOut}, height ${e.motionDurationSlow} ${e.motionEaseInOut}`,[`& ~ ${t}-item:not(${t}-item-selected):not(${t}-item-disabled)::after`]:{backgroundColor:"transparent"}}),[`&${t}-lg`]:{borderRadius:e.borderRadiusLG,[`${t}-item-label`]:{minHeight:a,lineHeight:n.unit(a),padding:`0 ${n.unit(e.segmentedPaddingHorizontal)}`,fontSize:e.fontSizeLG},[`${t}-item, ${t}-thumb`]:{borderRadius:e.borderRadius}},[`&${t}-sm`]:{borderRadius:e.borderRadiusSM,[`${t}-item-label`]:{minHeight:r,lineHeight:n.unit(r),padding:`0 ${n.unit(e.segmentedPaddingHorizontalSM)}`},[`${t}-item, ${t}-thumb`]:{borderRadius:e.borderRadiusXS}}}),Z(`&-disabled ${t}-item`,e)),Z(`${t}-item-disabled`,e)),{[`${t}-thumb-motion-appear-active`]:{transition:`transform ${e.motionDurationSlow} ${e.motionEaseInOut}, width ${e.motionDurationSlow} ${e.motionEaseInOut}`,willChange:"transform, width"},[`&${t}-shape-round`]:{borderRadius:9999,[`${t}-item, ${t}-thumb`]:{borderRadius:9999}}})}},ye=e=>{const{colorTextLabel:t,colorText:i,colorFillSecondary:a,colorBgElevated:r,colorFill:s,lineWidthBold:p,colorBgLayout:h}=e;return{trackPadding:p,trackBg:h,itemColor:t,itemHoverColor:i,itemHoverBg:a,itemSelectedBg:r,itemActiveBg:s,itemSelectedColor:i}},je=n.genStyleHooks("Segmented",e=>{const{lineWidth:t,calc:i}=e,a=n.merge(e,{segmentedPaddingHorizontal:i(e.controlPaddingHorizontal).sub(t).equal(),segmentedPaddingHorizontalSM:i(e.controlPaddingHorizontalSM).sub(t).equal()});return[Se(a)]},ye);var k=function(e,t){var i={};for(var a in e)Object.prototype.hasOwnProperty.call(e,a)&&t.indexOf(a)<0&&(i[a]=e[a]);if(e!=null&&typeof Object.getOwnPropertySymbols=="function")for(var r=0,a=Object.getOwnPropertySymbols(e);r<a.length;r++)t.indexOf(a[r])<0&&Object.prototype.propertyIsEnumerable.call(e,a[r])&&(i[a[r]]=e[a[r]]);return i};function $e(e){return typeof e=="object"&&!!(e!=null&&e.icon)}const we=o.forwardRef((e,t)=>{const i=n.useId(),{prefixCls:a,className:r,rootClassName:s,block:p,options:h=[],size:b="middle",style:S,vertical:d,shape:$="default",name:w=i}=e,R=k(e,["prefixCls","className","rootClassName","block","options","size","style","vertical","shape","name"]),{getPrefixCls:v,direction:M,className:C,style:E}=n.useComponentConfig("segmented"),f=v("segmented",a),[l,N,V]=je(f),x=n.useSize(b),c=o.useMemo(()=>h.map(O=>{if($e(O)){const{icon:D,label:H}=O,A=k(O,["icon","label"]);return Object.assign(Object.assign({},A),{label:o.createElement(o.Fragment,null,o.createElement("span",{className:`${f}-item-icon`},D),H&&o.createElement("span",null,H))})}return O}),[h,f]),I=n.cn(r,s,C,{[`${f}-block`]:p,[`${f}-sm`]:x==="small",[`${f}-lg`]:x==="large",[`${f}-vertical`]:d,[`${f}-shape-${$}`]:$==="round"},N,V),y=Object.assign(Object.assign({},E),S);return l(o.createElement(pe,Object.assign({},R,{name:w,className:I,style:y,options:c,ref:t,prefixCls:f,direction:M,vertical:d})))}),te=we;process.env.NODE_ENV!=="production"&&(te.displayName="Segmented");var Re={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M758.2 839.1C851.8 765.9 912 651.9 912 523.9 912 303 733.5 124.3 512.6 124 291.4 123.7 112 302.8 112 523.9c0 125.2 57.5 236.9 147.6 310.2 3.5 2.8 8.6 2.2 11.4-1.3l39.4-50.5c2.7-3.4 2.1-8.3-1.2-11.1-8.1-6.6-15.9-13.7-23.4-21.2a318.64 318.64 0 01-68.6-101.7C200.4 609 192 567.1 192 523.9s8.4-85.1 25.1-124.5c16.1-38.1 39.2-72.3 68.6-101.7 29.4-29.4 63.6-52.5 101.7-68.6C426.9 212.4 468.8 204 512 204s85.1 8.4 124.5 25.1c38.1 16.1 72.3 39.2 101.7 68.6 29.4 29.4 52.5 63.6 68.6 101.7 16.7 39.4 25.1 81.3 25.1 124.5s-8.4 85.1-25.1 124.5a318.64 318.64 0 01-68.6 101.7c-9.3 9.3-19.1 18-29.3 26L668.2 724a8 8 0 00-14.1 3l-39.6 162.2c-1.2 5 2.6 9.9 7.7 9.9l167 .8c6.7 0 10.5-7.7 6.3-12.9l-37.3-47.9z"}}]},name:"redo",theme:"outlined"};function W(){return W=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var i=arguments[t];for(var a in i)Object.prototype.hasOwnProperty.call(i,a)&&(e[a]=i[a])}return e},W.apply(this,arguments)}const Ce=(e,t)=>o.createElement(n.Icon,W({},e,{ref:t,icon:Re})),ne=o.forwardRef(Ce);process.env.NODE_ENV!=="production"&&(ne.displayName="RedoOutlined");const Oe=({datePickerComponent:e,searchText:t,noDateText:i,emptyText:a,searchSelect:r,radioOptions:s,searchOptions:p,searchType:h,textSearchValue:b="",dateSearchValue:S,numberSearchValue:d,multiselectSearchValue:$,multiselectOptions:w,onChangeSearch:R,onChangeTextSearch:v,onChangeRadioSearch:M,onChangeDateSearch:C,onChangeNumberSearch:E,onChangeMultiselectSearch:f})=>{const[l,N]=K.useState(b),{token:{borderRadius:V,colorBgBase:x,paddingXXS:c}}=n.theme.useToken(),{isMobileMaxWidth:I}=n.useMobileViewPort(),{isSmallMaxWidth:y}=n.useSmallViewPort(),O=K.useMemo(()=>y?2:I?5:15,[I,y]);n.useDebounce(()=>{v==null||v(l)},n.TIME.milliseconds.milliseconds500,[l]);const D=()=>{N("")},H=m=>{R(m),D()},A=m=>{N(m.target.value.replace(/"/g,""))},u=m=>{C==null||C(m)},P=m=>{!m&&m!==0||E==null||E(+m)};return n.jsxRuntimeExports.jsxs(n.Flex,{className:n.styles.flex,gap:"small",style:{padding:c,borderRadius:V,background:x},children:[n.jsxRuntimeExports.jsx(n.Select,{defaultValue:r,value:r,style:{width:120,minWidth:120},options:p,onChange:H}),{text:n.jsxRuntimeExports.jsx(n.Input,{placeholder:t,value:l,allowClear:!0,onChange:A}),radio:n.jsxRuntimeExports.jsx(te,{options:s,defaultValue:n.searchRadioDefaultValue,onChange:M}),date:K.createElement(e,{noDateText:i,currentValue:S??"",onChangeDate:u}),number:n.jsxRuntimeExports.jsx(n.BaseInputNumber,{emptyText:a,value:d,placeholder:t,min:0,max:2147483647,onChange:P}),multiselect:n.jsxRuntimeExports.jsx(n.Select,{className:n.styles.select,mode:"multiple",placeholder:t,maxTagCount:1,maxTagTextLength:O,showSearch:!1,allowClear:!0,options:w,value:$,onChange:f})}[h]]})},Ee=({sortTooltipText:e,updateDataText:t,refreshText:i,createText:a,createNewElementText:r,order:s,orderOptions:p,createButtonTooltip:h,searchProps:b,isCanCreate:S,isHiddenCreate:d,onCreate:$,onRefetch:w,onChangeOrder:R})=>n.jsxRuntimeExports.jsxs(n.Flex,{gap:"middle",justify:"space-between",wrap:"wrap",style:{marginBottom:n.THEME.OFFSET[1]},children:[n.jsxRuntimeExports.jsxs(n.Flex,{align:"center",gap:"middle",wrap:"wrap",children:[n.jsxRuntimeExports.jsx(Oe,{...b}),n.jsxRuntimeExports.jsx(n.Tooltip,{title:e,children:n.jsxRuntimeExports.jsx(n.Select,{className:n.styles.sort,value:s,options:p,onChange:R})})]}),n.jsxRuntimeExports.jsxs(n.Flex,{className:n.styles.buttonsContainer,gap:"small",align:"center",children:[w&&n.jsxRuntimeExports.jsx(n.Tooltip,{title:t,children:n.jsxRuntimeExports.jsx(n.Button,{className:n.styles.button,icon:n.jsxRuntimeExports.jsx(ne,{}),onClick:w,children:i})}),!d&&S&&n.jsxRuntimeExports.jsx(n.Tooltip,{title:h??r,children:n.jsxRuntimeExports.jsx(n.Button,{className:n.styles.button,type:"primary",icon:n.jsxRuntimeExports.jsx(n.RefIcon,{}),onClick:$,children:a})})]})]});exports.TableHead=Ee;
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("./index-n5OyW3Ln.cjs"),K=require("react");function me(e){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e){for(const i in e)if(i!=="default"){const a=Object.getOwnPropertyDescriptor(e,i);Object.defineProperty(t,i,a.get?a:{enumerable:!0,get:()=>e[i]})}}return t.default=e,Object.freeze(t)}const o=me(K);var J=function(t,i){if(!t)return null;var a={left:t.offsetLeft,right:t.parentElement.clientWidth-t.clientWidth-t.offsetLeft,width:t.clientWidth,top:t.offsetTop,bottom:t.parentElement.clientHeight-t.clientHeight-t.offsetTop,height:t.clientHeight};return i?{left:0,right:0,width:0,top:a.top,bottom:a.bottom,height:a.height}:{left:a.left,right:a.right,width:a.width,top:0,bottom:0,height:0}},T=function(t){return t!==void 0?"".concat(t,"px"):void 0};function fe(e){var t=e.prefixCls,i=e.containerRef,a=e.value,r=e.getValueIndex,s=e.motionName,p=e.onMotionStart,h=e.onMotionEnd,b=e.direction,S=e.vertical,d=S===void 0?!1:S,$=o.useRef(null),w=o.useState(a),R=n._slicedToArray(w,2),v=R[0],M=R[1],C=function(P){var m,B=r(P),_=(m=i.current)===null||m===void 0?void 0:m.querySelectorAll(".".concat(t,"-item"))[B];return(_==null?void 0:_.offsetParent)&&_},E=o.useState(null),f=n._slicedToArray(E,2),l=f[0],N=f[1],V=o.useState(null),x=n._slicedToArray(V,2),c=x[0],I=x[1];n.useLayoutEffect(function(){if(v!==a){var u=C(v),P=C(a),m=J(u,d),B=J(P,d);M(a),N(m),I(B),u&&P?p():h()}},[a]);var y=o.useMemo(function(){if(d){var u;return T((u=l==null?void 0:l.top)!==null&&u!==void 0?u:0)}return T(b==="rtl"?-(l==null?void 0:l.right):l==null?void 0:l.left)},[d,b,l]),O=o.useMemo(function(){if(d){var u;return T((u=c==null?void 0:c.top)!==null&&u!==void 0?u:0)}return T(b==="rtl"?-(c==null?void 0:c.right):c==null?void 0:c.left)},[d,b,c]),D=function(){return d?{transform:"translateY(var(--thumb-start-top))",height:"var(--thumb-start-height)"}:{transform:"translateX(var(--thumb-start-left))",width:"var(--thumb-start-width)"}},H=function(){return d?{transform:"translateY(var(--thumb-active-top))",height:"var(--thumb-active-height)"}:{transform:"translateX(var(--thumb-active-left))",width:"var(--thumb-active-width)"}},A=function(){N(null),I(null),h()};return!l||!c?null:o.createElement(n.CSSMotion,{visible:!0,motionName:s,motionAppear:!0,onAppearStart:D,onAppearActive:H,onVisibleChanged:A},function(u,P){var m=u.className,B=u.style,_=n._objectSpread2(n._objectSpread2({},B),{},{"--thumb-start-left":y,"--thumb-start-width":T(l==null?void 0:l.width),"--thumb-active-left":O,"--thumb-active-width":T(c==null?void 0:c.width),"--thumb-start-top":y,"--thumb-start-height":T(l==null?void 0:l.height),"--thumb-active-top":O,"--thumb-active-height":T(c==null?void 0:c.height)}),F={ref:n.composeRef($,P),style:_,className:n.cn("".concat(t,"-thumb"),m)};return process.env.NODE_ENV==="test"&&(F["data-test-style"]=JSON.stringify(_)),o.createElement("div",F)})}var ve=["prefixCls","direction","vertical","options","disabled","defaultValue","value","name","onChange","className","motionName"];function ge(e){if(typeof e.title<"u")return e.title;if(n._typeof(e.label)!=="object"){var t;return(t=e.label)===null||t===void 0?void 0:t.toString()}}function he(e){return e.map(function(t){if(n._typeof(t)==="object"&&t!==null){var i=ge(t);return n._objectSpread2(n._objectSpread2({},t),{},{title:i})}return{label:t==null?void 0:t.toString(),title:t==null?void 0:t.toString(),value:t}})}var be=function(t){var i=t.prefixCls,a=t.className,r=t.disabled,s=t.checked,p=t.label,h=t.title,b=t.value,S=t.name,d=t.onChange,$=t.onFocus,w=t.onBlur,R=t.onKeyDown,v=t.onKeyUp,M=t.onMouseDown,C=function(f){r||d(f,b)};return o.createElement("label",{className:n.cn(a,n._defineProperty({},"".concat(i,"-item-disabled"),r)),onMouseDown:M},o.createElement("input",{name:S,className:"".concat(i,"-item-input"),type:"radio",disabled:r,checked:s,onChange:C,onFocus:$,onBlur:w,onKeyDown:R,onKeyUp:v}),o.createElement("div",{className:"".concat(i,"-item-label"),title:h,"aria-selected":s},p))},ee=o.forwardRef(function(e,t){var i,a,r=e.prefixCls,s=r===void 0?"rc-segmented":r,p=e.direction,h=e.vertical,b=e.options,S=b===void 0?[]:b,d=e.disabled,$=e.defaultValue,w=e.value,R=e.name,v=e.onChange,M=e.className,C=M===void 0?"":M,E=e.motionName,f=E===void 0?"thumb-motion":E,l=n._objectWithoutProperties(e,ve),N=o.useRef(null),V=o.useMemo(function(){return n.composeRef(N,t)},[N,t]),x=o.useMemo(function(){return he(S)},[S]),c=n.useMergedState((i=x[0])===null||i===void 0?void 0:i.value,{value:w,defaultValue:$}),I=n._slicedToArray(c,2),y=I[0],O=I[1],D=o.useState(!1),H=n._slicedToArray(D,2),A=H[0],u=H[1],P=function(j,z){O(z),v==null||v(z)},m=n.omit(l,["children"]),B=o.useState(!1),_=n._slicedToArray(B,2),F=_[0],X=_[1],ae=o.useState(!1),q=n._slicedToArray(ae,2),ie=q[0],U=q[1],oe=function(){U(!0)},re=function(){U(!1)},le=function(){X(!1)},se=function(j){j.key==="Tab"&&X(!0)},G=function(j){var z=x.findIndex(function(de){return de.value===y}),Y=x.length,ue=(z+j+Y)%Y,L=x[ue];L&&(O(L.value),v==null||v(L.value))},ce=function(j){switch(j.key){case"ArrowLeft":case"ArrowUp":G(-1);break;case"ArrowRight":case"ArrowDown":G(1);break}};return o.createElement("div",n._extends({role:"radiogroup","aria-label":"segmented control",tabIndex:d?void 0:0},m,{className:n.cn(s,(a={},n._defineProperty(a,"".concat(s,"-rtl"),p==="rtl"),n._defineProperty(a,"".concat(s,"-disabled"),d),n._defineProperty(a,"".concat(s,"-vertical"),h),a),C),ref:V}),o.createElement("div",{className:"".concat(s,"-group")},o.createElement(fe,{vertical:h,prefixCls:s,value:y,containerRef:N,motionName:"".concat(s,"-").concat(f),direction:p,getValueIndex:function(j){return x.findIndex(function(z){return z.value===j})},onMotionStart:function(){u(!0)},onMotionEnd:function(){u(!1)}}),x.map(function(g){var j;return o.createElement(be,n._extends({},g,{name:R,key:g.value,prefixCls:s,className:n.cn(g.className,"".concat(s,"-item"),(j={},n._defineProperty(j,"".concat(s,"-item-selected"),g.value===y&&!A),n._defineProperty(j,"".concat(s,"-item-focused"),ie&&F&&g.value===y),j)),checked:g.value===y,onChange:P,onFocus:oe,onBlur:re,onKeyDown:ce,onKeyUp:se,onMouseDown:le,disabled:!!d||!!g.disabled}))})))});process.env.NODE_ENV!=="production"&&(ee.displayName="Segmented");var pe=ee;function Z(e,t){return{[`${e}, ${e}:hover, ${e}:focus`]:{color:t.colorTextDisabled,cursor:"not-allowed"}}}function Q(e){return{backgroundColor:e.itemSelectedBg,boxShadow:e.boxShadowTertiary}}const xe=Object.assign({overflow:"hidden"},n.textEllipsis),Se=e=>{const{componentCls:t}=e,i=e.calc(e.controlHeight).sub(e.calc(e.trackPadding).mul(2)).equal(),a=e.calc(e.controlHeightLG).sub(e.calc(e.trackPadding).mul(2)).equal(),r=e.calc(e.controlHeightSM).sub(e.calc(e.trackPadding).mul(2)).equal();return{[t]:Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},n.resetComponent(e)),{display:"inline-block",padding:e.trackPadding,color:e.itemColor,background:e.trackBg,borderRadius:e.borderRadius,transition:`all ${e.motionDurationMid} ${e.motionEaseInOut}`}),n.genFocusStyle(e)),{[`${t}-group`]:{position:"relative",display:"flex",alignItems:"stretch",justifyItems:"flex-start",flexDirection:"row",width:"100%"},[`&${t}-rtl`]:{direction:"rtl"},[`&${t}-vertical`]:{[`${t}-group`]:{flexDirection:"column"},[`${t}-thumb`]:{width:"100%",height:0,padding:`0 ${n.unit(e.paddingXXS)}`}},[`&${t}-block`]:{display:"flex"},[`&${t}-block ${t}-item`]:{flex:1,minWidth:0},[`${t}-item`]:{position:"relative",textAlign:"center",cursor:"pointer",transition:`color ${e.motionDurationMid} ${e.motionEaseInOut}`,borderRadius:e.borderRadiusSM,transform:"translateZ(0)","&-selected":Object.assign(Object.assign({},Q(e)),{color:e.itemSelectedColor}),"&-focused":Object.assign({},n.genFocusOutline(e)),"&::after":{content:'""',position:"absolute",zIndex:-1,width:"100%",height:"100%",top:0,insetInlineStart:0,borderRadius:"inherit",opacity:0,transition:`opacity ${e.motionDurationMid}`,pointerEvents:"none"},[`&:hover:not(${t}-item-selected):not(${t}-item-disabled)`]:{color:e.itemHoverColor,"&::after":{opacity:1,backgroundColor:e.itemHoverBg}},[`&:active:not(${t}-item-selected):not(${t}-item-disabled)`]:{color:e.itemHoverColor,"&::after":{opacity:1,backgroundColor:e.itemActiveBg}},"&-label":Object.assign({minHeight:i,lineHeight:n.unit(i),padding:`0 ${n.unit(e.segmentedPaddingHorizontal)}`},xe),"&-icon + *":{marginInlineStart:e.calc(e.marginSM).div(2).equal()},"&-input":{position:"absolute",insetBlockStart:0,insetInlineStart:0,width:0,height:0,opacity:0,pointerEvents:"none"}},[`${t}-thumb`]:Object.assign(Object.assign({},Q(e)),{position:"absolute",insetBlockStart:0,insetInlineStart:0,width:0,height:"100%",padding:`${n.unit(e.paddingXXS)} 0`,borderRadius:e.borderRadiusSM,transition:`transform ${e.motionDurationSlow} ${e.motionEaseInOut}, height ${e.motionDurationSlow} ${e.motionEaseInOut}`,[`& ~ ${t}-item:not(${t}-item-selected):not(${t}-item-disabled)::after`]:{backgroundColor:"transparent"}}),[`&${t}-lg`]:{borderRadius:e.borderRadiusLG,[`${t}-item-label`]:{minHeight:a,lineHeight:n.unit(a),padding:`0 ${n.unit(e.segmentedPaddingHorizontal)}`,fontSize:e.fontSizeLG},[`${t}-item, ${t}-thumb`]:{borderRadius:e.borderRadius}},[`&${t}-sm`]:{borderRadius:e.borderRadiusSM,[`${t}-item-label`]:{minHeight:r,lineHeight:n.unit(r),padding:`0 ${n.unit(e.segmentedPaddingHorizontalSM)}`},[`${t}-item, ${t}-thumb`]:{borderRadius:e.borderRadiusXS}}}),Z(`&-disabled ${t}-item`,e)),Z(`${t}-item-disabled`,e)),{[`${t}-thumb-motion-appear-active`]:{transition:`transform ${e.motionDurationSlow} ${e.motionEaseInOut}, width ${e.motionDurationSlow} ${e.motionEaseInOut}`,willChange:"transform, width"},[`&${t}-shape-round`]:{borderRadius:9999,[`${t}-item, ${t}-thumb`]:{borderRadius:9999}}})}},ye=e=>{const{colorTextLabel:t,colorText:i,colorFillSecondary:a,colorBgElevated:r,colorFill:s,lineWidthBold:p,colorBgLayout:h}=e;return{trackPadding:p,trackBg:h,itemColor:t,itemHoverColor:i,itemHoverBg:a,itemSelectedBg:r,itemActiveBg:s,itemSelectedColor:i}},je=n.genStyleHooks("Segmented",e=>{const{lineWidth:t,calc:i}=e,a=n.merge(e,{segmentedPaddingHorizontal:i(e.controlPaddingHorizontal).sub(t).equal(),segmentedPaddingHorizontalSM:i(e.controlPaddingHorizontalSM).sub(t).equal()});return[Se(a)]},ye);var k=function(e,t){var i={};for(var a in e)Object.prototype.hasOwnProperty.call(e,a)&&t.indexOf(a)<0&&(i[a]=e[a]);if(e!=null&&typeof Object.getOwnPropertySymbols=="function")for(var r=0,a=Object.getOwnPropertySymbols(e);r<a.length;r++)t.indexOf(a[r])<0&&Object.prototype.propertyIsEnumerable.call(e,a[r])&&(i[a[r]]=e[a[r]]);return i};function $e(e){return typeof e=="object"&&!!(e!=null&&e.icon)}const we=o.forwardRef((e,t)=>{const i=n.useId(),{prefixCls:a,className:r,rootClassName:s,block:p,options:h=[],size:b="middle",style:S,vertical:d,shape:$="default",name:w=i}=e,R=k(e,["prefixCls","className","rootClassName","block","options","size","style","vertical","shape","name"]),{getPrefixCls:v,direction:M,className:C,style:E}=n.useComponentConfig("segmented"),f=v("segmented",a),[l,N,V]=je(f),x=n.useSize(b),c=o.useMemo(()=>h.map(O=>{if($e(O)){const{icon:D,label:H}=O,A=k(O,["icon","label"]);return Object.assign(Object.assign({},A),{label:o.createElement(o.Fragment,null,o.createElement("span",{className:`${f}-item-icon`},D),H&&o.createElement("span",null,H))})}return O}),[h,f]),I=n.cn(r,s,C,{[`${f}-block`]:p,[`${f}-sm`]:x==="small",[`${f}-lg`]:x==="large",[`${f}-vertical`]:d,[`${f}-shape-${$}`]:$==="round"},N,V),y=Object.assign(Object.assign({},E),S);return l(o.createElement(pe,Object.assign({},R,{name:w,className:I,style:y,options:c,ref:t,prefixCls:f,direction:M,vertical:d})))}),te=we;process.env.NODE_ENV!=="production"&&(te.displayName="Segmented");var Re={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M758.2 839.1C851.8 765.9 912 651.9 912 523.9 912 303 733.5 124.3 512.6 124 291.4 123.7 112 302.8 112 523.9c0 125.2 57.5 236.9 147.6 310.2 3.5 2.8 8.6 2.2 11.4-1.3l39.4-50.5c2.7-3.4 2.1-8.3-1.2-11.1-8.1-6.6-15.9-13.7-23.4-21.2a318.64 318.64 0 01-68.6-101.7C200.4 609 192 567.1 192 523.9s8.4-85.1 25.1-124.5c16.1-38.1 39.2-72.3 68.6-101.7 29.4-29.4 63.6-52.5 101.7-68.6C426.9 212.4 468.8 204 512 204s85.1 8.4 124.5 25.1c38.1 16.1 72.3 39.2 101.7 68.6 29.4 29.4 52.5 63.6 68.6 101.7 16.7 39.4 25.1 81.3 25.1 124.5s-8.4 85.1-25.1 124.5a318.64 318.64 0 01-68.6 101.7c-9.3 9.3-19.1 18-29.3 26L668.2 724a8 8 0 00-14.1 3l-39.6 162.2c-1.2 5 2.6 9.9 7.7 9.9l167 .8c6.7 0 10.5-7.7 6.3-12.9l-37.3-47.9z"}}]},name:"redo",theme:"outlined"};function W(){return W=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var i=arguments[t];for(var a in i)Object.prototype.hasOwnProperty.call(i,a)&&(e[a]=i[a])}return e},W.apply(this,arguments)}const Ce=(e,t)=>o.createElement(n.Icon,W({},e,{ref:t,icon:Re})),ne=o.forwardRef(Ce);process.env.NODE_ENV!=="production"&&(ne.displayName="RedoOutlined");const Oe=({datePickerComponent:e,searchText:t,noDateText:i,emptyText:a,searchSelect:r,radioOptions:s,searchOptions:p,searchType:h,textSearchValue:b="",dateSearchValue:S,numberSearchValue:d,multiselectSearchValue:$,multiselectOptions:w,onChangeSearch:R,onChangeTextSearch:v,onChangeRadioSearch:M,onChangeDateSearch:C,onChangeNumberSearch:E,onChangeMultiselectSearch:f})=>{const[l,N]=K.useState(b),{token:{borderRadius:V,colorBgBase:x,paddingXXS:c}}=n.theme.useToken(),{isMobileMaxWidth:I}=n.useMobileViewPort(),{isSmallMaxWidth:y}=n.useSmallViewPort(),O=K.useMemo(()=>y?2:I?5:15,[I,y]);n.useDebounce(()=>{v==null||v(l)},n.TIME.milliseconds.milliseconds500,[l]);const D=()=>{N("")},H=m=>{R(m),D()},A=m=>{N(m.target.value.replace(/"/g,""))},u=m=>{C==null||C(m)},P=m=>{!m&&m!==0||E==null||E(+m)};return n.jsxRuntimeExports.jsxs(n.Flex,{className:n.styles.flex,gap:"small",style:{padding:c,borderRadius:V,background:x},children:[n.jsxRuntimeExports.jsx(n.Select,{defaultValue:r,value:r,style:{width:120,minWidth:120},options:p,onChange:H}),{text:n.jsxRuntimeExports.jsx(n.Input,{placeholder:t,value:l,allowClear:!0,onChange:A}),radio:n.jsxRuntimeExports.jsx(te,{options:s,defaultValue:n.searchRadioDefaultValue,onChange:M}),date:K.createElement(e,{noDateText:i,currentValue:S??"",onChangeDate:u}),number:n.jsxRuntimeExports.jsx(n.BaseInputNumber,{emptyText:a,value:d,placeholder:t,min:0,max:2147483647,onChange:P}),multiselect:n.jsxRuntimeExports.jsx(n.Select,{className:n.styles.select,mode:"multiple",placeholder:t,maxTagCount:1,maxTagTextLength:O,showSearch:!1,allowClear:!0,options:w,value:$,onChange:f})}[h]]})},Ee=({sortTooltipText:e,updateDataText:t,refreshText:i,createText:a,createNewElementText:r,order:s,orderOptions:p,createButtonTooltip:h,searchProps:b,isCanCreate:S,isHiddenCreate:d,onCreate:$,onRefetch:w,onChangeOrder:R})=>n.jsxRuntimeExports.jsxs(n.Flex,{gap:"middle",justify:"space-between",wrap:"wrap",style:{marginBottom:n.THEME.OFFSET[1]},children:[n.jsxRuntimeExports.jsxs(n.Flex,{align:"center",gap:"middle",wrap:"wrap",children:[n.jsxRuntimeExports.jsx(Oe,{...b}),n.jsxRuntimeExports.jsx(n.Tooltip,{title:e,children:n.jsxRuntimeExports.jsx(n.Select,{className:n.styles.sort,value:s,options:p,onChange:R})})]}),n.jsxRuntimeExports.jsxs(n.Flex,{className:n.styles.buttonsContainer,gap:"small",align:"center",children:[w&&n.jsxRuntimeExports.jsx(n.Tooltip,{title:t,children:n.jsxRuntimeExports.jsx(n.Button,{className:n.styles.button,icon:n.jsxRuntimeExports.jsx(ne,{}),onClick:w,children:i})}),!d&&S&&n.jsxRuntimeExports.jsx(n.Tooltip,{title:h??r,children:n.jsxRuntimeExports.jsx(n.Button,{className:n.styles.button,type:"primary",icon:n.jsxRuntimeExports.jsx(n.RefIcon,{}),onClick:$,children:a})})]})]});exports.TableHead=Ee;
|
package/package.json
CHANGED
|
@@ -1,13 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "denwa-react-shared",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.89",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "Denwa",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"react",
|
|
9
|
+
"shared",
|
|
10
|
+
"admin",
|
|
11
|
+
"tanstack-intent"
|
|
12
|
+
],
|
|
7
13
|
"main": "dist/denwa-react-shared.umd.js",
|
|
8
14
|
"module": "dist/denwa-react-shared.es.js",
|
|
9
15
|
"files": [
|
|
10
|
-
"dist"
|
|
16
|
+
"dist",
|
|
17
|
+
"skills",
|
|
18
|
+
"!skills/_artifacts"
|
|
11
19
|
],
|
|
12
20
|
"types": "dist/index.d.ts",
|
|
13
21
|
"exports": {
|
|
@@ -63,6 +71,7 @@
|
|
|
63
71
|
"@types/react": "^19.1.6",
|
|
64
72
|
"@types/react-dom": "^19.1.6",
|
|
65
73
|
"@types/validator": "^13.15.1",
|
|
74
|
+
"@tanstack/intent": "latest",
|
|
66
75
|
"@vitejs/plugin-react-swc": "^3.10.1",
|
|
67
76
|
"autoprefixer": "^10.4.21",
|
|
68
77
|
"eslint": "^9.28.0",
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: admin-forms
|
|
3
|
+
description: >
|
|
4
|
+
Implement entity editor forms using DrawerForm and specialized inputs.
|
|
5
|
+
Covers form submission, language switching, and integration with
|
|
6
|
+
AdminTable actions.
|
|
7
|
+
type: framework
|
|
8
|
+
library: denwa-react-shared
|
|
9
|
+
framework: react
|
|
10
|
+
library_version: "1.0.88"
|
|
11
|
+
requires:
|
|
12
|
+
- session-auth
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# Drawer Forms & Inputs
|
|
16
|
+
|
|
17
|
+
Most entity management in the admin panel happens within `Drawer` panels using `BaseDrawerForm`. This component standardizes the appearance of save buttons and multi-language controls.
|
|
18
|
+
|
|
19
|
+
## Setup
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
import { BaseDrawerForm, AdminDrawerFormProps } from 'denwa-react-shared';
|
|
23
|
+
|
|
24
|
+
const UserForm = ({ id, action, onClose, onRefetch }: AdminDrawerFormProps<'create' | 'update' | 'read'>) => {
|
|
25
|
+
const { control, handleSubmit } = useForm();
|
|
26
|
+
|
|
27
|
+
const isReadOnly = action === 'read';
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<BaseDrawerForm
|
|
31
|
+
saveText="Сохранить"
|
|
32
|
+
submitButtonText={action === 'create' ? 'Создать' : 'Обновить'}
|
|
33
|
+
isVisibleSubmit={!isReadOnly}
|
|
34
|
+
onSubmitClick={handleSubmit(onSave)}
|
|
35
|
+
>
|
|
36
|
+
<Controller
|
|
37
|
+
name="name"
|
|
38
|
+
control={control}
|
|
39
|
+
render={({ field }) => <Input {...field} disabled={isReadOnly} />}
|
|
40
|
+
/>
|
|
41
|
+
{/* ... form content */}
|
|
42
|
+
</BaseDrawerForm>
|
|
43
|
+
);
|
|
44
|
+
};
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Core Patterns
|
|
48
|
+
|
|
49
|
+
### Language Switching
|
|
50
|
+
If the entity supports multiple languages, enable `isVisibleLanguage` and provide `languagesData`.
|
|
51
|
+
|
|
52
|
+
```tsx
|
|
53
|
+
<BaseDrawerForm
|
|
54
|
+
isVisibleLanguage
|
|
55
|
+
language={currentLang}
|
|
56
|
+
languagesData={[
|
|
57
|
+
{ label: 'Русский', value: 'ru' },
|
|
58
|
+
{ label: 'English', value: 'en' },
|
|
59
|
+
]}
|
|
60
|
+
onChangeLang={(lang) => setLang(lang)}
|
|
61
|
+
// Optional: Bulk translation button
|
|
62
|
+
isVisibleLanguageButton
|
|
63
|
+
translateAllText="Перевести все"
|
|
64
|
+
onTranslateAllClick={handleTranslate}
|
|
65
|
+
>
|
|
66
|
+
{/* ... fields */}
|
|
67
|
+
</BaseDrawerForm>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Integration with AdminTable
|
|
71
|
+
The `AdminTable` orchestration passes `id`, `action`, `onClose`, and `onRefetch` to the `drawerContent` component.
|
|
72
|
+
|
|
73
|
+
```tsx
|
|
74
|
+
// In AdminTable:
|
|
75
|
+
<AdminTable
|
|
76
|
+
drawerContent={UserForm}
|
|
77
|
+
readAction="read"
|
|
78
|
+
createAction="create"
|
|
79
|
+
updateAction="update"
|
|
80
|
+
// ...
|
|
81
|
+
/>
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Common Mistakes
|
|
85
|
+
|
|
86
|
+
### MEDIUM Using raw antd Form
|
|
87
|
+
Wrong:
|
|
88
|
+
```tsx
|
|
89
|
+
import { Form } from 'antd';
|
|
90
|
+
return <Form>{children}</Form>;
|
|
91
|
+
```
|
|
92
|
+
Correct:
|
|
93
|
+
```tsx
|
|
94
|
+
import { BaseDrawerForm } from 'denwa-react-shared';
|
|
95
|
+
return <BaseDrawerForm>{children}</BaseDrawerForm>;
|
|
96
|
+
```
|
|
97
|
+
`BaseDrawerForm` wraps `antd` Form but adds standardized footer buttons and integrated logic for language switching and submission loading states.
|
|
98
|
+
|
|
99
|
+
Source: maintainer interview
|
|
100
|
+
|
|
101
|
+
### HIGH Mismanaging "read" action state
|
|
102
|
+
Wrong:
|
|
103
|
+
```tsx
|
|
104
|
+
const UserForm = ({ action }) => {
|
|
105
|
+
return <BaseDrawerForm>{/* inputs are always enabled */}</BaseDrawerForm>;
|
|
106
|
+
};
|
|
107
|
+
```
|
|
108
|
+
Correct:
|
|
109
|
+
```tsx
|
|
110
|
+
const UserForm = ({ action }) => {
|
|
111
|
+
const isReadOnly = action === 'read';
|
|
112
|
+
return (
|
|
113
|
+
<BaseDrawerForm isVisibleSubmit={!isReadOnly}>
|
|
114
|
+
<Input disabled={isReadOnly} />
|
|
115
|
+
</BaseDrawerForm>
|
|
116
|
+
);
|
|
117
|
+
};
|
|
118
|
+
```
|
|
119
|
+
When `action` is 'read', the form should visually hide the submit button and disable all input fields.
|
|
120
|
+
|
|
121
|
+
Source: src/shared/ui/admin-table/index.tsx
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: admin-table
|
|
3
|
+
description: >
|
|
4
|
+
Implement complex data tables using AdminTable and useFetchTableData.
|
|
5
|
+
Covers columns configuration, server-side filtering, sorting,
|
|
6
|
+
and search state mapping.
|
|
7
|
+
type: framework
|
|
8
|
+
library: denwa-react-shared
|
|
9
|
+
framework: react
|
|
10
|
+
library_version: "1.0.88"
|
|
11
|
+
requires:
|
|
12
|
+
- session-auth
|
|
13
|
+
sources:
|
|
14
|
+
- "Denwa799/react-shared:src/shared/ui/admin-table/index.tsx"
|
|
15
|
+
- "Denwa799/react-shared:src/shared/lib/hooks/use-fetch-table-data.ts"
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
# Admin Table & Data Fetching
|
|
19
|
+
|
|
20
|
+
The `AdminTable` component is the centerpiece for building resource lists. It works in conjunction with `useFetchTableData` to map UI states (search, sort, page) to API filters.
|
|
21
|
+
|
|
22
|
+
## Setup
|
|
23
|
+
|
|
24
|
+
```tsx
|
|
25
|
+
import { AdminTable, useFetchTableData } from 'denwa-react-shared';
|
|
26
|
+
import { ColumnsType } from 'antd/es/table';
|
|
27
|
+
|
|
28
|
+
const UsersPage = () => {
|
|
29
|
+
// 1. Setup state setters (usually from nuqs or local state)
|
|
30
|
+
const [order, setOrder] = useState('createdAtDesc');
|
|
31
|
+
const [search, setSearch] = useState('');
|
|
32
|
+
|
|
33
|
+
// 2. Use hook to get mapped filters/sort for API
|
|
34
|
+
const { filter, sort, onChangeOrder, ...searchHandlers } = useFetchTableData({
|
|
35
|
+
order,
|
|
36
|
+
search,
|
|
37
|
+
onSetOrder: setOrder,
|
|
38
|
+
onSetSearch: setSearch,
|
|
39
|
+
// ... other setters for pagination, radio, date search
|
|
40
|
+
sortFields: [{ key: 'createdAtDesc', field: 'createdAt', order: 'desc' }],
|
|
41
|
+
searchFields: ['name', 'email'],
|
|
42
|
+
// ... field configuration
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// 3. Render table
|
|
46
|
+
return (
|
|
47
|
+
<AdminTable
|
|
48
|
+
tableData={data}
|
|
49
|
+
columns={columns}
|
|
50
|
+
order={order}
|
|
51
|
+
onChangeOrder={onChangeOrder}
|
|
52
|
+
searchProps={{
|
|
53
|
+
...searchHandlers,
|
|
54
|
+
// ... text labels
|
|
55
|
+
}}
|
|
56
|
+
// ... actions and text props
|
|
57
|
+
/>
|
|
58
|
+
);
|
|
59
|
+
};
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Core Patterns
|
|
63
|
+
|
|
64
|
+
### Configuring Search and Filters
|
|
65
|
+
`searchProps` expects a `TableSearchProps` object. Ensure you provide the `datePickerComponent` and all required handlers from `useFetchTableData`.
|
|
66
|
+
|
|
67
|
+
```tsx
|
|
68
|
+
<AdminTable
|
|
69
|
+
searchProps={{
|
|
70
|
+
datePickerComponent: BaseDatePicker,
|
|
71
|
+
searchText: 'Поиск',
|
|
72
|
+
noDateText: 'Нет даты',
|
|
73
|
+
emptyText: 'Ничего не найдено',
|
|
74
|
+
searchSelect: currentSearchField,
|
|
75
|
+
radioOptions: [{ label: 'Все', value: 'all' }],
|
|
76
|
+
searchOptions: [{ label: 'Имя', value: 'name' }],
|
|
77
|
+
searchType: 'text',
|
|
78
|
+
onChangeSearch: handleFieldChange,
|
|
79
|
+
onChangeTextSearch: handleTextChange,
|
|
80
|
+
}}
|
|
81
|
+
// ...
|
|
82
|
+
/>
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Server-Side Pagination
|
|
86
|
+
The table expects `serverPagination` prop of type `IPaginate`.
|
|
87
|
+
|
|
88
|
+
```tsx
|
|
89
|
+
<AdminTable
|
|
90
|
+
serverPagination={{
|
|
91
|
+
total: totalItems,
|
|
92
|
+
page: currentPage,
|
|
93
|
+
limit: pageSize,
|
|
94
|
+
}}
|
|
95
|
+
onSetPaginate={(page, limit) => {
|
|
96
|
+
setPage(page);
|
|
97
|
+
setLimit(limit);
|
|
98
|
+
}}
|
|
99
|
+
/>
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Common Mistakes
|
|
103
|
+
|
|
104
|
+
### HIGH Hallucinating internal state management
|
|
105
|
+
Wrong:
|
|
106
|
+
```tsx
|
|
107
|
+
// Trying to use useFetchTableData without passing external setters
|
|
108
|
+
const tableInfo = useFetchTableData({
|
|
109
|
+
order: 'desc', // Static value
|
|
110
|
+
// Missing onSetOrder, onSetSearch, etc.
|
|
111
|
+
});
|
|
112
|
+
```
|
|
113
|
+
Correct:
|
|
114
|
+
```tsx
|
|
115
|
+
const [order, setOrder] = useState('desc');
|
|
116
|
+
const tableInfo = useFetchTableData({
|
|
117
|
+
order,
|
|
118
|
+
onSetOrder: setOrder,
|
|
119
|
+
// Must provide setters to allow the hook to update external state
|
|
120
|
+
});
|
|
121
|
+
```
|
|
122
|
+
The hook acts as a logic mapper and relies on external state (like `nuqs` or `useState`) to persist changes.
|
|
123
|
+
|
|
124
|
+
Source: maintainer interview
|
|
125
|
+
|
|
126
|
+
### HIGH Passings wrong pagination format
|
|
127
|
+
Wrong:
|
|
128
|
+
```tsx
|
|
129
|
+
// Using antd internal pagination object
|
|
130
|
+
<AdminTable serverPagination={{ current: 1, pageSize: 10 }} />
|
|
131
|
+
```
|
|
132
|
+
Correct:
|
|
133
|
+
```tsx
|
|
134
|
+
<AdminTable serverPagination={{ page: 1, limit: 10, total: 100 }} />
|
|
135
|
+
```
|
|
136
|
+
`AdminTable` expects a custom `IPaginate` shape, not the standard Ant Design pagination object.
|
|
137
|
+
|
|
138
|
+
Source: src/shared/ui/admin-table/types.ts
|
|
139
|
+
|
|
140
|
+
### MEDIUM Using raw antd Table
|
|
141
|
+
Wrong:
|
|
142
|
+
```tsx
|
|
143
|
+
import { Table } from 'antd';
|
|
144
|
+
return <Table dataSource={data} columns={columns} />;
|
|
145
|
+
```
|
|
146
|
+
Correct:
|
|
147
|
+
```tsx
|
|
148
|
+
import { AdminTable } from 'denwa-react-shared';
|
|
149
|
+
return <AdminTable tableData={data} columns={columns} ... />;
|
|
150
|
+
```
|
|
151
|
+
Using raw `Table` loses integrated search UI, standardized skeletons, and the "Drawer Form" orchestration.
|
|
152
|
+
|
|
153
|
+
Source: maintainer interview
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: material-map
|
|
3
|
+
description: >
|
|
4
|
+
Integrate Yandex Maps for coordinate selection. Covers map initialization,
|
|
5
|
+
setting markers, and coordinate synchronization.
|
|
6
|
+
type: framework
|
|
7
|
+
library: denwa-react-shared
|
|
8
|
+
framework: react
|
|
9
|
+
library_version: "1.0.88"
|
|
10
|
+
requires:
|
|
11
|
+
- session-auth
|
|
12
|
+
sources:
|
|
13
|
+
- "Denwa799/react-shared:src/shared/ui/material-map/index.tsx"
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
# Yandex Maps Integration
|
|
17
|
+
|
|
18
|
+
`BaseMaterialMap` uses Yandex Maps to allow users to select geographic coordinates. It requires a Yandex Maps API key and provides a simple interface for single-point selection.
|
|
19
|
+
|
|
20
|
+
## Setup
|
|
21
|
+
|
|
22
|
+
```tsx
|
|
23
|
+
import { BaseMaterialMap } from 'denwa-react-shared';
|
|
24
|
+
|
|
25
|
+
const LocationPicker = () => {
|
|
26
|
+
return (
|
|
27
|
+
<BaseMaterialMap
|
|
28
|
+
apiKey="your-yandex-api-key"
|
|
29
|
+
value={{ lat: 55.751244, lng: 37.618423 }}
|
|
30
|
+
onChange={(coords) => setLocation(coords)}
|
|
31
|
+
height={400}
|
|
32
|
+
zoom={10}
|
|
33
|
+
noDataText="Координаты не выбраны"
|
|
34
|
+
/>
|
|
35
|
+
);
|
|
36
|
+
};
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Core Patterns
|
|
40
|
+
|
|
41
|
+
### Manual Coordinate Entry
|
|
42
|
+
The component displays the current coordinates in inputs. Users can either click on the map or type values manually. Always ensure `onChange` is provided to capture changes from both sources.
|
|
43
|
+
|
|
44
|
+
### Custom Height and Styling
|
|
45
|
+
The map container should be constrained by the `height` prop. It defaults to `100%` width of the parent container.
|
|
46
|
+
|
|
47
|
+
## Common Mistakes
|
|
48
|
+
|
|
49
|
+
### CRITICAL Missing API Key
|
|
50
|
+
Wrong:
|
|
51
|
+
```tsx
|
|
52
|
+
<BaseMaterialMap value={coords} />
|
|
53
|
+
```
|
|
54
|
+
Correct:
|
|
55
|
+
```tsx
|
|
56
|
+
<BaseMaterialMap apiKey={import.meta.env.VITE_YAMAP_KEY} value={coords} />
|
|
57
|
+
```
|
|
58
|
+
The map uses `@iminside/react-yandex-maps` internally. If the `apiKey` is missing or invalid, the map will fail to load or will show a "Demo mode" watermark.
|
|
59
|
+
|
|
60
|
+
Source: src/shared/ui/material-map/index.tsx
|
|
61
|
+
|
|
62
|
+
### HIGH Forgetting default center for empty values
|
|
63
|
+
If the `value` is undefined, the map might center on a default (often 0,0) or fail. Always provide a fallback `defaultCenter` or check for existence.
|
|
64
|
+
|
|
65
|
+
Source: maintainer interview
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: media-management
|
|
3
|
+
description: >
|
|
4
|
+
Handle single/multiple image uploads and file attachments.
|
|
5
|
+
Covers drag-and-drop sorting, temporary upload patterns,
|
|
6
|
+
and media deletion.
|
|
7
|
+
type: framework
|
|
8
|
+
library: denwa-react-shared
|
|
9
|
+
framework: react
|
|
10
|
+
library_version: "1.0.88"
|
|
11
|
+
requires:
|
|
12
|
+
- session-auth
|
|
13
|
+
sources:
|
|
14
|
+
- "Denwa799/react-shared:src/shared/ui/image-upload/base-image-upload.tsx"
|
|
15
|
+
- "Denwa799/react-shared:src/shared/ui/file-upload/file-upload.tsx"
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
# Media & File Management
|
|
19
|
+
|
|
20
|
+
The library provides `BaseImageUpload` for image galleries and `FileUpload` for general documents. Both rely on a two-step process: uploading to a temporary location first, then associating the path with the entity.
|
|
21
|
+
|
|
22
|
+
## Setup
|
|
23
|
+
|
|
24
|
+
### Image Upload with Sorting
|
|
25
|
+
```tsx
|
|
26
|
+
import { BaseImageUpload, TAdminImage } from 'denwa-react-shared';
|
|
27
|
+
|
|
28
|
+
const Gallery = () => {
|
|
29
|
+
return (
|
|
30
|
+
<BaseImageUpload
|
|
31
|
+
isMultiple
|
|
32
|
+
label="Галерея"
|
|
33
|
+
images={images}
|
|
34
|
+
onUpdateTempImage={handleTempUpload}
|
|
35
|
+
onUpdateItems={handleReorder}
|
|
36
|
+
onUpdateDeleteItems={handleDelete}
|
|
37
|
+
/>
|
|
38
|
+
);
|
|
39
|
+
};
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Core Patterns
|
|
43
|
+
|
|
44
|
+
### Two-Step Upload Process
|
|
45
|
+
Components emit native File objects. You must upload these to a temporary storage API and return the resulting path to the component's state.
|
|
46
|
+
|
|
47
|
+
```tsx
|
|
48
|
+
const handleTempUpload = async (file: File) => {
|
|
49
|
+
const formData = new FormData();
|
|
50
|
+
formData.append('file', file);
|
|
51
|
+
|
|
52
|
+
const response = await api.upload(formData); // Your API
|
|
53
|
+
return response.path; // e.g. "/temp/random-id.png"
|
|
54
|
+
};
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### File Attachments
|
|
58
|
+
For non-image files, use `FileUpload`. It supports single or multiple files with size/extension limits.
|
|
59
|
+
|
|
60
|
+
```tsx
|
|
61
|
+
import { FileUpload } from 'denwa-react-shared';
|
|
62
|
+
|
|
63
|
+
<FileUpload
|
|
64
|
+
label="Документ"
|
|
65
|
+
onUpload={handleFileUpload}
|
|
66
|
+
onRemove={handleFileRemove}
|
|
67
|
+
items={data.files}
|
|
68
|
+
isMultiple={false}
|
|
69
|
+
/>
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Common Mistakes
|
|
73
|
+
|
|
74
|
+
### CRITICAL Forgetting to handle reordering
|
|
75
|
+
Wrong:
|
|
76
|
+
```tsx
|
|
77
|
+
// Only handling uploads
|
|
78
|
+
<BaseImageUpload onUpdateTempImage={upload} />
|
|
79
|
+
```
|
|
80
|
+
Correct:
|
|
81
|
+
```tsx
|
|
82
|
+
<BaseImageUpload
|
|
83
|
+
onUpdateTempImage={upload}
|
|
84
|
+
onUpdateItems={(newItems) => setImages(newItems)}
|
|
85
|
+
/>
|
|
86
|
+
```
|
|
87
|
+
If `onUpdateItems` is missing, drag-and-drop reordering will visually work but won't persist to state.
|
|
88
|
+
|
|
89
|
+
Source: src/shared/ui/image-upload/base-image-upload.tsx
|
|
90
|
+
|
|
91
|
+
### HIGH Passing only URLs instead of Image objects
|
|
92
|
+
Wrong:
|
|
93
|
+
```tsx
|
|
94
|
+
<BaseImageUpload images={["/image1.png"]} />
|
|
95
|
+
```
|
|
96
|
+
Correct:
|
|
97
|
+
```tsx
|
|
98
|
+
<BaseImageUpload images={[{ id: 1, path: "/image1.png" }]} />
|
|
99
|
+
```
|
|
100
|
+
`BaseImageUpload` expects an array of objects containing `id` and `path`, not raw strings.
|
|
101
|
+
|
|
102
|
+
Source: src/shared/ui/image-upload/types.ts
|
|
103
|
+
|
|
104
|
+
### MEDIUM Missing upload button due to limits
|
|
105
|
+
If the `limit` prop is reached, the "Upload" button disappears. Ensure you communicate this UI behavior or provide a way to delete items.
|
|
106
|
+
|
|
107
|
+
Source: src/shared/ui/image-upload/base-image-upload.tsx:55
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: session-auth
|
|
3
|
+
description: >
|
|
4
|
+
Manage authentication sessions, parse server responses, and validate identity
|
|
5
|
+
cookies using Zod schemas. Use for handling login flow results and
|
|
6
|
+
session integrity checks.
|
|
7
|
+
type: core
|
|
8
|
+
library: denwa-react-shared
|
|
9
|
+
library_version: "1.0.88"
|
|
10
|
+
sources:
|
|
11
|
+
- "Denwa799/react-shared:src/shared/schemas/index.ts"
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Session & Auth Management
|
|
15
|
+
|
|
16
|
+
This skill covers the standardization of server responses and session state validation using Zod schemas. All API interactions should be validated against these schemas to ensure data consistency.
|
|
17
|
+
|
|
18
|
+
## Setup
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
import { responseSchema, sessionCookieSchema } from 'denwa-react-shared';
|
|
22
|
+
|
|
23
|
+
// Example: Validating an API response
|
|
24
|
+
const handleApiResponse = (data: unknown) => {
|
|
25
|
+
const result = responseSchema.safeParse(data);
|
|
26
|
+
if (!result.success) {
|
|
27
|
+
console.error('API format mismatch:', result.error);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
return result.data;
|
|
31
|
+
};
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Core Patterns
|
|
35
|
+
|
|
36
|
+
### Parsing Session Cookies
|
|
37
|
+
Use `sessionCookieSchema` to validate the structure of the authentication cookie before using it in the application.
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
import { sessionCookieSchema } from 'denwa-react-shared';
|
|
41
|
+
|
|
42
|
+
const validateSession = (cookieData: unknown) => {
|
|
43
|
+
const session = sessionCookieSchema.parse(cookieData);
|
|
44
|
+
return {
|
|
45
|
+
isLoggedIn: !!session.tokens.accessToken.token,
|
|
46
|
+
userRoles: session.roles,
|
|
47
|
+
isAdmin: session.roles.includes('admin'),
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Handling Standard Error Envelopes
|
|
53
|
+
The `responseSchema` includes a structured `error` field. Always check for both the top-level `error` object and `statusCode`.
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
import { responseSchema } from 'denwa-react-shared';
|
|
57
|
+
|
|
58
|
+
async function fetchData(url: string) {
|
|
59
|
+
const response = await fetch(url);
|
|
60
|
+
const data = await response.json();
|
|
61
|
+
|
|
62
|
+
const parsed = responseSchema.parse(data);
|
|
63
|
+
if (parsed.error) {
|
|
64
|
+
throw new Error(parsed.error.message || 'Unknown error');
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return parsed.data;
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Common Mistakes
|
|
72
|
+
|
|
73
|
+
### MEDIUM Manually parsing cookies without schema
|
|
74
|
+
Wrong:
|
|
75
|
+
```typescript
|
|
76
|
+
const id = JSON.parse(cookies.get('session')).id;
|
|
77
|
+
```
|
|
78
|
+
Correct:
|
|
79
|
+
```typescript
|
|
80
|
+
const session = sessionCookieSchema.parse(cookies.get('session'));
|
|
81
|
+
const id = session.id;
|
|
82
|
+
```
|
|
83
|
+
Manually accessing properties bypasses validation and creates runtime risks if the session structure changes.
|
|
84
|
+
|
|
85
|
+
Source: maintainer interview
|
|
86
|
+
|
|
87
|
+
### HIGH Ignoring the data/response duality
|
|
88
|
+
Wrong:
|
|
89
|
+
```typescript
|
|
90
|
+
// Expecting data to always be the result
|
|
91
|
+
const users = response.data;
|
|
92
|
+
```
|
|
93
|
+
Correct:
|
|
94
|
+
```typescript
|
|
95
|
+
// Checking both data and any legacy response fields
|
|
96
|
+
const users = response.data ?? response.response;
|
|
97
|
+
```
|
|
98
|
+
The `responseSchema` allows for flexibility in return fields (`data` vs `response`). Agents should account for both.
|
|
99
|
+
|
|
100
|
+
Source: src/shared/schemas/index.ts
|