@easy-editor/materials-dashboard-carousel 0.0.2 → 0.0.4

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/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @easy-editor/materials-dashboard-carousel
2
2
 
3
+ ## 0.0.4
4
+
5
+ ### Patch Changes
6
+
7
+ - perf: configure & datasource
8
+ - Updated dependencies
9
+ - @easy-editor/materials-shared@0.0.1
10
+
11
+ ## 0.0.3
12
+
13
+ ### Patch Changes
14
+
15
+ - fix: build error
16
+
3
17
  ## 0.0.2
4
18
 
5
19
  ### Patch Changes
@@ -0,0 +1 @@
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react"),require("react/jsx-runtime")):"function"==typeof define&&define.amd?define(["exports","react","react/jsx-runtime"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).EasyEditorMaterialsCarouselComponent={},e.React,e.jsxRuntime)}(this,function(e,t,o){"use strict";const n=(e,t)=>{if(!t)return e;const o=t.split(".");let n=e;for(const e of o){if(null==n)return;if("object"!=typeof n)return;n=n[e]}return n},r=e=>void 0===e?[]:Array.isArray(e)?e:e&&"object"==typeof e?[e]:[],a=(e,t)=>{const o=((e,t)=>{if(!e)return[];if("static"===e.sourceType)return Array.isArray(e.staticData)?e.staticData:[];if("global"===e.sourceType&&e.datasourceId){const o=t?.page?.[e.datasourceId];return r(o)}if("datasource"===e.sourceType&&e.datasourceId){const o=t?.component?.[e.datasourceId];return r(o)}return[]})(e,t);return((e,t)=>t&&0!==t.length?e.map(e=>{const o={};for(const{componentField:r,sourceField:a}of t)r&&a&&(o[r]=n(e,a));return o}):e)(o,e?.fieldMappings)};const s=(e,t,o)=>({type:"group",title:e,setter:{componentName:"CollapseSetter",props:{icon:!1,...o}},items:t});s("基础配置",[{name:"title",title:"标题",setter:"StringSetter",extraProps:{getValue:e=>e.getExtraPropValue("title"),setValue(e,t){e.setExtraPropValue("title",t)}}},{name:"rect",title:"位置尺寸",setter:"RectSetter",extraProps:{getValue:e=>e.getExtraPropValue("$dashboard.rect"),setValue(e,t){e.setExtraPropValue("$dashboard.rect",t)}}},{name:"rotation",title:"旋转角度",setter:{componentName:"SliderSetter",props:{min:0,max:360,suffix:"°"}},extraProps:{defaultValue:0}},{name:"opacity",title:"不透明度",setter:{componentName:"SliderSetter",props:{min:0,max:100,suffix:"%"}},extraProps:{defaultValue:100}},{name:"background",title:"背景颜色",setter:"ColorSetter",extraProps:{defaultValue:"transparent"}}]);const i=[{title:"点击事件",children:[{label:"点击",value:"onClick",description:"鼠标点击时触发"},{label:"双击",value:"onDoubleClick",description:"鼠标双击时触发"}]},{title:"鼠标事件",children:[{label:"鼠标进入",value:"onMouseEnter",description:"鼠标进入时触发"},{label:"鼠标离开",value:"onMouseLeave",description:"鼠标离开时触发"}]}];((e=i)=>{s("事件绑定",[{name:"events",title:"事件",setter:{componentName:"EventSetter",props:{events:e}},extraProps:{label:!1}}])})(),s("高级配置",[{title:"条件渲染",setter:"SwitchSetter",extraProps:{supportVariable:!0,getValue:e=>e.getNode().getExtraPropValue("condition"),setValue(e,t){e.getNode().setExtraProp("condition",t)}}}]);var l="component-module__container___VbZSk",c="component-module__track___I-5nr",d="component-module__slide___7N5m5",u="component-module__slideImage___CJ8fn",p="component-module__navButton___0CqxY",m="component-module__navButtonPrev___qAqle",_="component-module__navButtonNext___yYw7n",h="component-module__indicators___WMttK",f="component-module__indicator___KYoys",x="component-module__indicatorActive___ws6eP";!function(e,t){void 0===t&&(t={});var o=t.insertAt;if("undefined"!=typeof document){var n=document.head||document.getElementsByTagName("head")[0],r=document.createElement("style");r.type="text/css","top"===o&&n.firstChild?n.insertBefore(r,n.firstChild):n.appendChild(r),r.styleSheet?r.styleSheet.cssText=e:r.appendChild(document.createTextNode(e))}}(".component-module__container___VbZSk{border-radius:8px;height:100%;overflow:hidden;position:relative;width:100%}.component-module__track___I-5nr{display:flex;height:100%;transition:transform .5s ease}.component-module__slide___7N5m5{align-items:center;display:flex;flex:0 0 100%;height:100%;justify-content:center;width:100%}.component-module__slideImage___CJ8fn{height:100%;object-fit:cover;width:100%}.component-module__navButton___0CqxY{align-items:center;background:rgba(0,0,0,.5);border:none;border-radius:50%;color:#fff;cursor:pointer;display:flex;height:40px;justify-content:center;position:absolute;top:50%;transform:translateY(-50%);transition:background .3s ease;width:40px;z-index:10}.component-module__navButton___0CqxY:hover{background:rgba(0,0,0,.7)}.component-module__navButtonPrev___qAqle{left:16px}.component-module__navButtonNext___yYw7n{right:16px}.component-module__indicators___WMttK{bottom:16px;display:flex;gap:8px;left:50%;position:absolute;transform:translateX(-50%);z-index:10}.component-module__indicator___KYoys{background:hsla(0,0%,100%,.4);border:none;border-radius:50%;cursor:pointer;height:8px;padding:0;transition:all .3s ease;width:8px}.component-module__indicatorActive___ws6eP{background:#fff;transform:scale(1.2)}.component-module__indicator___KYoys:hover{background:hsla(0,0%,100%,.7)}");const g=[{src:"https://picsum.photos/800/400?random=1",alt:"Slide 1"},{src:"https://picsum.photos/800/400?random=2",alt:"Slide 2"},{src:"https://picsum.photos/800/400?random=3",alt:"Slide 3"}],b=()=>o.jsxs("svg",{"aria-hidden":"true",fill:"none",height:"24",stroke:"currentColor",strokeWidth:"2",viewBox:"0 0 24 24",width:"24",children:[o.jsx("title",{children:"Previous"}),o.jsx("path",{d:"M15 18l-6-6 6-6"})]}),v=()=>o.jsxs("svg",{"aria-hidden":"true",fill:"none",height:"24",stroke:"currentColor",strokeWidth:"2",viewBox:"0 0 24 24",width:"24",children:[o.jsx("title",{children:"Next"}),o.jsx("path",{d:"M9 18l6-6-6-6"})]});e.Carousel=({ref:e,$data:n,__dataSource:r,autoPlay:s=!0,interval:i=3e3,showNav:y=!0,showIndicators:k=!0,loop:C=!0,rotation:j,opacity:N,background:S,style:P,onClick:w,onDoubleClick:V,onMouseEnter:E,onMouseLeave:M,onChange:$})=>{const[B,I]=t.useState(0),q=function(e,o){return t.useMemo(()=>a(e,o),[e,o])}(n,r),A=t.useMemo(()=>q.length>0?q:g,[q]),Y=t.useCallback(()=>{I(e=>{const t=e>=A.length-1?C?0:e:e+1;return t!==e&&$?.(t),t})},[A.length,C,$]),T=t.useCallback(()=>{I(e=>{const t=e<=0?C?A.length-1:e:e-1;return t!==e&&$?.(t),t})},[A.length,C,$]),D=t.useCallback(e=>{I(e),$?.(e)},[$]);if(t.useEffect(()=>{if(!s||A.length<=1)return;const e=setInterval(Y,i);return()=>clearInterval(e)},[s,i,Y,A.length]),0===A.length)return null;const K={transform:j?`rotate(${j}deg)`:void 0,opacity:void 0!==N?N/100:void 0,backgroundColor:S,...P};return o.jsxs("div",{className:l,onClick:w,onDoubleClick:V,onMouseEnter:E,onMouseLeave:M,ref:e,style:K,children:[o.jsx("div",{className:c,style:{transform:`translateX(-${100*B}%)`},children:A.map((e,t)=>o.jsx("div",{className:d,children:e.link?o.jsx("a",{href:e.link,rel:"noopener noreferrer",target:"_blank",children:o.jsx("img",{alt:e.alt||"",className:u,draggable:!1,height:"200",src:e.src,width:"100%"})}):o.jsx("img",{alt:e.alt||"",className:u,draggable:!1,height:"200",src:e.src,width:"100%"})},t))}),y&&A.length>1&&o.jsxs(o.Fragment,{children:[o.jsx("button",{"aria-label":"Previous slide",className:`${p} ${m}`,onClick:T,type:"button",children:o.jsx(b,{})}),o.jsx("button",{"aria-label":"Next slide",className:`${p} ${_}`,onClick:Y,type:"button",children:o.jsx(v,{})})]}),k&&A.length>1&&o.jsx("div",{className:h,children:A.map((e,t)=>o.jsx("button",{"aria-label":`Go to slide ${t+1}`,className:`${f} ${t===B?x:""}`,onClick:()=>D(t),type:"button"},t))})]})}});
package/dist/index.min.js CHANGED
@@ -1,2 +1 @@
1
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react"),require("react/jsx-runtime")):"function"==typeof define&&define.amd?define(["exports","react","react/jsx-runtime"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).EasyEditorMaterialsCarousel={},e.React,e.jsxRuntime)}(this,function(e,t,o){"use strict";var r="component-module__container___VbZSk",a="component-module__track___I-5nr",n="component-module__slide___7N5m5",s="component-module__slideImage___CJ8fn",i="component-module__navButton___0CqxY",l="component-module__navButtonPrev___qAqle",d="component-module__navButtonNext___yYw7n",c="component-module__indicators___WMttK",p="component-module__indicator___KYoys",m="component-module__indicatorActive___ws6eP";!function(e,t){void 0===t&&(t={});var o=t.insertAt;if("undefined"!=typeof document){var r=document.head||document.getElementsByTagName("head")[0],a=document.createElement("style");a.type="text/css","top"===o&&r.firstChild?r.insertBefore(a,r.firstChild):r.appendChild(a),a.styleSheet?a.styleSheet.cssText=e:a.appendChild(document.createTextNode(e))}}(".component-module__container___VbZSk{border-radius:8px;height:100%;overflow:hidden;position:relative;width:100%}.component-module__track___I-5nr{display:flex;height:100%;transition:transform .5s ease}.component-module__slide___7N5m5{align-items:center;display:flex;flex:0 0 100%;height:100%;justify-content:center;width:100%}.component-module__slideImage___CJ8fn{height:100%;object-fit:cover;width:100%}.component-module__navButton___0CqxY{align-items:center;background:rgba(0,0,0,.5);border:none;border-radius:50%;color:#fff;cursor:pointer;display:flex;height:40px;justify-content:center;position:absolute;top:50%;transform:translateY(-50%);transition:background .3s ease;width:40px;z-index:10}.component-module__navButton___0CqxY:hover{background:rgba(0,0,0,.7)}.component-module__navButtonPrev___qAqle{left:16px}.component-module__navButtonNext___yYw7n{right:16px}.component-module__indicators___WMttK{bottom:16px;display:flex;gap:8px;left:50%;position:absolute;transform:translateX(-50%);z-index:10}.component-module__indicator___KYoys{background:hsla(0,0%,100%,.4);border:none;border-radius:50%;cursor:pointer;height:8px;padding:0;transition:all .3s ease;width:8px}.component-module__indicatorActive___ws6eP{background:#fff;transform:scale(1.2)}.component-module__indicator___KYoys:hover{background:hsla(0,0%,100%,.7)}");const u=[{src:"https://picsum.photos/800/400?random=1",alt:"Slide 1"},{src:"https://picsum.photos/800/400?random=2",alt:"Slide 2"},{src:"https://picsum.photos/800/400?random=3",alt:"Slide 3"}],h=()=>o.jsxs("svg",{"aria-hidden":"true",fill:"none",height:"24",stroke:"currentColor",strokeWidth:"2",viewBox:"0 0 24 24",width:"24",children:[o.jsx("title",{children:"Previous"}),o.jsx("path",{d:"M15 18l-6-6 6-6"})]}),_=()=>o.jsxs("svg",{"aria-hidden":"true",fill:"none",height:"24",stroke:"currentColor",strokeWidth:"2",viewBox:"0 0 24 24",width:"24",children:[o.jsx("title",{children:"Next"}),o.jsx("path",{d:"M9 18l6-6-6-6"})]}),g="EasyEditorMaterialsCarousel";const x={componentName:g,title:"轮播",group:"display",devMode:"proCode",npm:{package:"@easy-editor/materials-dashboard-carousel",version:"0.0.1",globalName:g,componentName:g},snippets:[{title:"图片轮播",screenshot:"",schema:{componentName:g,props:{items:[{src:"https://picsum.photos/800/400?random=1",alt:"Slide 1"},{src:"https://picsum.photos/800/400?random=2",alt:"Slide 2"},{src:"https://picsum.photos/800/400?random=3",alt:"Slide 3"}],autoPlay:!0,interval:3e3,showNav:!0,showIndicators:!0,loop:!0},$dashboard:{rect:{width:600,height:300}}}},{title:"手动轮播",screenshot:"",schema:{componentName:g,props:{items:[{src:"https://picsum.photos/800/400?random=4",alt:"Slide 1"},{src:"https://picsum.photos/800/400?random=5",alt:"Slide 2"}],autoPlay:!1,showNav:!0,showIndicators:!0,loop:!0},$dashboard:{rect:{width:600,height:300}}}}],configure:{props:[{type:"group",title:"属性",setter:"TabSetter",items:[{type:"group",key:"config",title:"配置",setter:{componentName:"CollapseSetter",props:{icon:!1}},items:[{name:"id",title:"ID",setter:"NodeIdSetter",extraProps:{label:!1}},{name:"title",title:"标题",setter:"StringSetter",extraProps:{getValue:e=>e.getExtraPropValue("title"),setValue(e,t){e.setExtraPropValue("title",t)}}},{type:"group",title:"基础属性",setter:{componentName:"CollapseSetter",props:{icon:!1}},items:[{name:"rect",title:"位置尺寸",setter:"RectSetter",extraProps:{getValue:e=>e.getExtraPropValue("$dashboard.rect"),setValue(e,t){e.setExtraPropValue("$dashboard.rect",t)}}}]},{type:"group",title:"数据",setter:{componentName:"CollapseSetter",props:{icon:!1}},items:[{name:"items",title:"轮播项",setter:"JsonSetter"}]},{type:"group",title:"行为",setter:{componentName:"CollapseSetter",props:{icon:!1}},items:[{name:"autoPlay",title:"自动播放",setter:"SwitchSetter",extraProps:{defaultValue:!0}},{name:"interval",title:"播放间隔(ms)",setter:"NumberSetter",extraProps:{defaultValue:3e3}},{name:"loop",title:"循环播放",setter:"SwitchSetter",extraProps:{defaultValue:!0}}]},{type:"group",title:"显示",setter:{componentName:"CollapseSetter",props:{icon:!1}},items:[{name:"showNav",title:"显示导航按钮",setter:"SwitchSetter",extraProps:{defaultValue:!0}},{name:"showIndicators",title:"显示指示器",setter:"SwitchSetter",extraProps:{defaultValue:!0}}]}]},{type:"group",key:"data",title:"数据",items:[{name:"dataBinding",title:"数据绑定",setter:"DataBindingSetter"}]},{type:"group",key:"advanced",title:"高级",items:[{name:"condition",title:"显隐控制",setter:"SwitchSetter",extraProps:{defaultValue:!0,supportVariable:!0}}]}]}],component:{},supports:{},advanced:{}}};e.component=({ref:e,items:g=u,autoPlay:x=!0,interval:f=3e3,showNav:b=!0,showIndicators:y=!0,loop:v=!0,style:S})=>{const[N,w]=t.useState(0),k=t.useCallback(()=>{w(e=>e>=g.length-1?v?0:e:e+1)},[g.length,v]),j=t.useCallback(()=>{w(e=>e<=0?v?g.length-1:e:e-1)},[g.length,v]),C=t.useCallback(e=>{w(e)},[]);return t.useEffect(()=>{if(!x||g.length<=1)return;const e=setInterval(k,f);return()=>clearInterval(e)},[x,f,k,g.length]),0===g.length?null:o.jsxs("div",{className:r,ref:e,style:S,children:[o.jsx("div",{className:a,style:{transform:`translateX(-${100*N}%)`},children:g.map((e,t)=>o.jsx("div",{className:n,children:e.link?o.jsx("a",{href:e.link,rel:"noopener noreferrer",target:"_blank",children:o.jsx("img",{alt:e.alt||"",className:s,draggable:!1,height:"200",src:e.src,width:"100%"})}):o.jsx("img",{alt:e.alt||"",className:s,draggable:!1,height:"200",src:e.src,width:"100%"})},t))}),b&&g.length>1&&o.jsxs(o.Fragment,{children:[o.jsx("button",{"aria-label":"Previous slide",className:`${i} ${l}`,onClick:j,type:"button",children:o.jsx(h,{})}),o.jsx("button",{"aria-label":"Next slide",className:`${i} ${d}`,onClick:k,type:"button",children:o.jsx(_,{})})]}),y&&g.length>1&&o.jsx("div",{className:c,children:g.map((e,t)=>o.jsx("button",{"aria-label":`Go to slide ${t+1}`,className:`${p} ${t===N?m:""}`,onClick:()=>C(t),type:"button"},t))})]})},e.meta=x});
2
- //# sourceMappingURL=index.min.js.map
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react"),require("react/jsx-runtime")):"function"==typeof define&&define.amd?define(["exports","react","react/jsx-runtime"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).EasyEditorMaterialsCarousel={},e.React,e.jsxRuntime)}(this,function(e,t,o){"use strict";const r=(e,t)=>{if(!t)return e;const o=t.split(".");let r=e;for(const e of o){if(null==r)return;if("object"!=typeof r)return;r=r[e]}return r},a=e=>void 0===e?[]:Array.isArray(e)?e:e&&"object"==typeof e?[e]:[],n=(e,t)=>{const o=((e,t)=>{if(!e)return[];if("static"===e.sourceType)return Array.isArray(e.staticData)?e.staticData:[];if("global"===e.sourceType&&e.datasourceId){const o=t?.page?.[e.datasourceId];return a(o)}if("datasource"===e.sourceType&&e.datasourceId){const o=t?.component?.[e.datasourceId];return a(o)}return[]})(e,t);return((e,t)=>t&&0!==t.length?e.map(e=>{const o={};for(const{componentField:a,sourceField:n}of t)a&&n&&(o[a]=r(e,n));return o}):e)(o,e?.fieldMappings)};const s=(e,t)=>{const o=Array.isArray(e)?e:[e],r=o[0]||{};return{sourceType:"static",staticData:o,fieldMappings:Object.keys(r).map(e=>({componentField:e,sourceField:e}))}},i=(e,t,o)=>({type:"group",title:e,setter:{componentName:"CollapseSetter",props:{icon:!1,...o}},items:t}),l={name:"nodeInfo",title:"节点信息",setter:"NodeInfoSetter",extraProps:{label:!1}},c=i("基础配置",[{name:"title",title:"标题",setter:"StringSetter",extraProps:{getValue:e=>e.getExtraPropValue("title"),setValue(e,t){e.setExtraPropValue("title",t)}}},{name:"rect",title:"位置尺寸",setter:"RectSetter",extraProps:{getValue:e=>e.getExtraPropValue("$dashboard.rect"),setValue(e,t){e.setExtraPropValue("$dashboard.rect",t)}}},{name:"rotation",title:"旋转角度",setter:{componentName:"SliderSetter",props:{min:0,max:360,suffix:"°"}},extraProps:{defaultValue:0}},{name:"opacity",title:"不透明度",setter:{componentName:"SliderSetter",props:{min:0,max:100,suffix:"%"}},extraProps:{defaultValue:100}},{name:"background",title:"背景颜色",setter:"ColorSetter",extraProps:{defaultValue:"transparent"}}]),d=[{title:"点击事件",children:[{label:"点击",value:"onClick",description:"鼠标点击时触发"},{label:"双击",value:"onDoubleClick",description:"鼠标双击时触发"}]},{title:"鼠标事件",children:[{label:"鼠标进入",value:"onMouseEnter",description:"鼠标进入时触发"},{label:"鼠标离开",value:"onMouseLeave",description:"鼠标离开时触发"}]}],p=((e=d)=>i("事件绑定",[{name:"events",title:"事件",setter:{componentName:"EventSetter",props:{events:e}},extraProps:{label:!1}}]))(),u=i("高级配置",[{title:"条件渲染",setter:"SwitchSetter",extraProps:{supportVariable:!0,getValue:e=>e.getNode().getExtraPropValue("condition"),setValue(e,t){e.getNode().setExtraProp("condition",t)}}}]);var m="component-module__container___VbZSk",h="component-module__track___I-5nr",_="component-module__slide___7N5m5",f="component-module__slideImage___CJ8fn",g="component-module__navButton___0CqxY",x="component-module__navButtonPrev___qAqle",b="component-module__navButtonNext___yYw7n",y="component-module__indicators___WMttK",v="component-module__indicator___KYoys",k="component-module__indicatorActive___ws6eP";!function(e,t){void 0===t&&(t={});var o=t.insertAt;if("undefined"!=typeof document){var r=document.head||document.getElementsByTagName("head")[0],a=document.createElement("style");a.type="text/css","top"===o&&r.firstChild?r.insertBefore(a,r.firstChild):r.appendChild(a),a.styleSheet?a.styleSheet.cssText=e:a.appendChild(document.createTextNode(e))}}(".component-module__container___VbZSk{border-radius:8px;height:100%;overflow:hidden;position:relative;width:100%}.component-module__track___I-5nr{display:flex;height:100%;transition:transform .5s ease}.component-module__slide___7N5m5{align-items:center;display:flex;flex:0 0 100%;height:100%;justify-content:center;width:100%}.component-module__slideImage___CJ8fn{height:100%;object-fit:cover;width:100%}.component-module__navButton___0CqxY{align-items:center;background:rgba(0,0,0,.5);border:none;border-radius:50%;color:#fff;cursor:pointer;display:flex;height:40px;justify-content:center;position:absolute;top:50%;transform:translateY(-50%);transition:background .3s ease;width:40px;z-index:10}.component-module__navButton___0CqxY:hover{background:rgba(0,0,0,.7)}.component-module__navButtonPrev___qAqle{left:16px}.component-module__navButtonNext___yYw7n{right:16px}.component-module__indicators___WMttK{bottom:16px;display:flex;gap:8px;left:50%;position:absolute;transform:translateX(-50%);z-index:10}.component-module__indicator___KYoys{background:hsla(0,0%,100%,.4);border:none;border-radius:50%;cursor:pointer;height:8px;padding:0;transition:all .3s ease;width:8px}.component-module__indicatorActive___ws6eP{background:#fff;transform:scale(1.2)}.component-module__indicator___KYoys:hover{background:hsla(0,0%,100%,.7)}");const S=[{src:"https://picsum.photos/800/400?random=1",alt:"Slide 1"},{src:"https://picsum.photos/800/400?random=2",alt:"Slide 2"},{src:"https://picsum.photos/800/400?random=3",alt:"Slide 3"}],N=()=>o.jsxs("svg",{"aria-hidden":"true",fill:"none",height:"24",stroke:"currentColor",strokeWidth:"2",viewBox:"0 0 24 24",width:"24",children:[o.jsx("title",{children:"Previous"}),o.jsx("path",{d:"M15 18l-6-6 6-6"})]}),w=()=>o.jsxs("svg",{"aria-hidden":"true",fill:"none",height:"24",stroke:"currentColor",strokeWidth:"2",viewBox:"0 0 24 24",width:"24",children:[o.jsx("title",{children:"Next"}),o.jsx("path",{d:"M9 18l6-6-6-6"})]}),P="EasyEditorMaterialsCarousel";const C=((e,t)=>({props:[{type:"group",title:"属性",setter:"TabSetter",items:[{type:"group",key:"config",title:"配置",items:[l,c,e]},{type:"group",key:"data",title:"数据",items:[l,t]},{type:"group",key:"advanced",title:"高级",items:[l,p,u]}]}],component:{},supports:{},advanced:{}}))(i("组件配置",[{type:"group",title:"组件配置",setter:"SubTabSetter",items:[{type:"group",key:"behavior",title:"行为",items:[{name:"autoPlay",title:"自动播放",setter:"SwitchSetter",extraProps:{defaultValue:!0}},{name:"interval",title:"播放间隔",setter:{componentName:"SliderSetter",props:{min:1e3,max:1e4,step:500,suffix:"ms"}},extraProps:{defaultValue:3e3}},{name:"loop",title:"循环播放",setter:"SwitchSetter",extraProps:{defaultValue:!0}}]},{type:"group",key:"display",title:"显示",items:[{name:"showNav",title:"显示导航按钮",setter:"SwitchSetter",extraProps:{defaultValue:!0}},{name:"showIndicators",title:"显示指示器",setter:"SwitchSetter",extraProps:{defaultValue:!0}}]}]}],{padding:"6px 16px 12px"}),{name:"$data",title:"数据配置",setter:{componentName:"DataSetter",props:{expectedFields:[{name:"src",label:"src",type:"string",required:!0,description:"图片地址"},{name:"alt",label:"alt",type:"string",required:!1,description:"图片描述"},{name:"link",label:"link",type:"string",required:!1,description:"点击链接"}],showPreview:!0,previewLimit:10}},extraProps:{label:!1}});const j={componentName:P,title:"轮播",group:"display",devMode:"proCode",npm:{package:"@easy-editor/materials-dashboard-carousel",version:"0.0.4",globalName:P,componentName:P},snippets:[{title:"图片轮播",screenshot:"",schema:{componentName:P,title:"图片轮播",props:{$data:s([{src:"https://picsum.photos/800/400?random=1",alt:"Slide 1"},{src:"https://picsum.photos/800/400?random=2",alt:"Slide 2"},{src:"https://picsum.photos/800/400?random=3",alt:"Slide 3"}]),autoPlay:!0,interval:3e3,showNav:!0,showIndicators:!0,loop:!0,rotation:0,opacity:100,background:"transparent"},$dashboard:{rect:{width:600,height:300}}}},{title:"手动轮播",screenshot:"",schema:{componentName:P,title:"手动轮播",props:{$data:s([{src:"https://picsum.photos/800/400?random=4",alt:"Slide 1"},{src:"https://picsum.photos/800/400?random=5",alt:"Slide 2"}]),autoPlay:!1,showNav:!0,showIndicators:!0,loop:!0,rotation:0,opacity:100,background:"transparent"},$dashboard:{rect:{width:600,height:300}}}}],configure:C};e.component=({ref:e,$data:r,__dataSource:a,autoPlay:s=!0,interval:i=3e3,showNav:l=!0,showIndicators:c=!0,loop:d=!0,rotation:p,opacity:u,background:P,style:C,onClick:j,onDoubleClick:V,onMouseEnter:E,onMouseLeave:M,onChange:$})=>{const[I,q]=t.useState(0),A=function(e,o){return t.useMemo(()=>n(e,o),[e,o])}(r,a),B=t.useMemo(()=>A.length>0?A:S,[A]),T=t.useCallback(()=>{q(e=>{const t=e>=B.length-1?d?0:e:e+1;return t!==e&&$?.(t),t})},[B.length,d,$]),Y=t.useCallback(()=>{q(e=>{const t=e<=0?d?B.length-1:e:e-1;return t!==e&&$?.(t),t})},[B.length,d,$]),D=t.useCallback(e=>{q(e),$?.(e)},[$]);if(t.useEffect(()=>{if(!s||B.length<=1)return;const e=setInterval(T,i);return()=>clearInterval(e)},[s,i,T,B.length]),0===B.length)return null;const F={transform:p?`rotate(${p}deg)`:void 0,opacity:void 0!==u?u/100:void 0,backgroundColor:P,...C};return o.jsxs("div",{className:m,onClick:j,onDoubleClick:V,onMouseEnter:E,onMouseLeave:M,ref:e,style:F,children:[o.jsx("div",{className:h,style:{transform:`translateX(-${100*I}%)`},children:B.map((e,t)=>o.jsx("div",{className:_,children:e.link?o.jsx("a",{href:e.link,rel:"noopener noreferrer",target:"_blank",children:o.jsx("img",{alt:e.alt||"",className:f,draggable:!1,height:"200",src:e.src,width:"100%"})}):o.jsx("img",{alt:e.alt||"",className:f,draggable:!1,height:"200",src:e.src,width:"100%"})},t))}),l&&B.length>1&&o.jsxs(o.Fragment,{children:[o.jsx("button",{"aria-label":"Previous slide",className:`${g} ${x}`,onClick:Y,type:"button",children:o.jsx(N,{})}),o.jsx("button",{"aria-label":"Next slide",className:`${g} ${b}`,onClick:T,type:"button",children:o.jsx(w,{})})]}),c&&B.length>1&&o.jsx("div",{className:y,children:B.map((e,t)=>o.jsx("button",{"aria-label":`Go to slide ${t+1}`,className:`${v} ${t===I?k:""}`,onClick:()=>D(t),type:"button"},t))})]})},e.meta=j});
@@ -0,0 +1 @@
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react")):"function"==typeof define&&define.amd?define(["exports","react"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).EasyEditorMaterialsCarouselMeta={})}(this,function(e){"use strict";const t=(e,t)=>{const a=Array.isArray(e)?e:[e],r=a[0]||{};return{sourceType:"static",staticData:a,fieldMappings:Object.keys(r).map(e=>({componentField:e,sourceField:e}))}},a=(e,t,a)=>({type:"group",title:e,setter:{componentName:"CollapseSetter",props:{icon:!1,...a}},items:t}),r={name:"nodeInfo",title:"节点信息",setter:"NodeInfoSetter",extraProps:{label:!1}},o=a("基础配置",[{name:"title",title:"标题",setter:"StringSetter",extraProps:{getValue:e=>e.getExtraPropValue("title"),setValue(e,t){e.setExtraPropValue("title",t)}}},{name:"rect",title:"位置尺寸",setter:"RectSetter",extraProps:{getValue:e=>e.getExtraPropValue("$dashboard.rect"),setValue(e,t){e.setExtraPropValue("$dashboard.rect",t)}}},{name:"rotation",title:"旋转角度",setter:{componentName:"SliderSetter",props:{min:0,max:360,suffix:"°"}},extraProps:{defaultValue:0}},{name:"opacity",title:"不透明度",setter:{componentName:"SliderSetter",props:{min:0,max:100,suffix:"%"}},extraProps:{defaultValue:100}},{name:"background",title:"背景颜色",setter:"ColorSetter",extraProps:{defaultValue:"transparent"}}]),s=[{title:"点击事件",children:[{label:"点击",value:"onClick",description:"鼠标点击时触发"},{label:"双击",value:"onDoubleClick",description:"鼠标双击时触发"}]},{title:"鼠标事件",children:[{label:"鼠标进入",value:"onMouseEnter",description:"鼠标进入时触发"},{label:"鼠标离开",value:"onMouseLeave",description:"鼠标离开时触发"}]}],i=((e=s)=>a("事件绑定",[{name:"events",title:"事件",setter:{componentName:"EventSetter",props:{events:e}},extraProps:{label:!1}}]))(),l=a("高级配置",[{title:"条件渲染",setter:"SwitchSetter",extraProps:{supportVariable:!0,getValue:e=>e.getNode().getExtraPropValue("condition"),setValue(e,t){e.getNode().setExtraProp("condition",t)}}}]),p="EasyEditorMaterialsCarousel";const n=((e,t)=>({props:[{type:"group",title:"属性",setter:"TabSetter",items:[{type:"group",key:"config",title:"配置",items:[r,o,e]},{type:"group",key:"data",title:"数据",items:[r,t]},{type:"group",key:"advanced",title:"高级",items:[r,i,l]}]}],component:{},supports:{},advanced:{}}))(a("组件配置",[{type:"group",title:"组件配置",setter:"SubTabSetter",items:[{type:"group",key:"behavior",title:"行为",items:[{name:"autoPlay",title:"自动播放",setter:"SwitchSetter",extraProps:{defaultValue:!0}},{name:"interval",title:"播放间隔",setter:{componentName:"SliderSetter",props:{min:1e3,max:1e4,step:500,suffix:"ms"}},extraProps:{defaultValue:3e3}},{name:"loop",title:"循环播放",setter:"SwitchSetter",extraProps:{defaultValue:!0}}]},{type:"group",key:"display",title:"显示",items:[{name:"showNav",title:"显示导航按钮",setter:"SwitchSetter",extraProps:{defaultValue:!0}},{name:"showIndicators",title:"显示指示器",setter:"SwitchSetter",extraProps:{defaultValue:!0}}]}]}],{padding:"6px 16px 12px"}),{name:"$data",title:"数据配置",setter:{componentName:"DataSetter",props:{expectedFields:[{name:"src",label:"src",type:"string",required:!0,description:"图片地址"},{name:"alt",label:"alt",type:"string",required:!1,description:"图片描述"},{name:"link",label:"link",type:"string",required:!1,description:"点击链接"}],showPreview:!0,previewLimit:10}},extraProps:{label:!1}});const d={componentName:p,title:"轮播",group:"display",devMode:"proCode",npm:{package:"@easy-editor/materials-dashboard-carousel",version:"0.0.4",globalName:p,componentName:p},snippets:[{title:"图片轮播",screenshot:"",schema:{componentName:p,title:"图片轮播",props:{$data:t([{src:"https://picsum.photos/800/400?random=1",alt:"Slide 1"},{src:"https://picsum.photos/800/400?random=2",alt:"Slide 2"},{src:"https://picsum.photos/800/400?random=3",alt:"Slide 3"}]),autoPlay:!0,interval:3e3,showNav:!0,showIndicators:!0,loop:!0,rotation:0,opacity:100,background:"transparent"},$dashboard:{rect:{width:600,height:300}}}},{title:"手动轮播",screenshot:"",schema:{componentName:p,title:"手动轮播",props:{$data:t([{src:"https://picsum.photos/800/400?random=4",alt:"Slide 1"},{src:"https://picsum.photos/800/400?random=5",alt:"Slide 2"}]),autoPlay:!1,showNav:!0,showIndicators:!0,loop:!0,rotation:0,opacity:100,background:"transparent"},$dashboard:{rect:{width:600,height:300}}}}],configure:n};e.meta=d});
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @easy-editor/easypack configuration
3
+ * @type {import('@easy-editor/easypack').EasypackConfig}
4
+ */
5
+ export default {
6
+ preset: 'material',
7
+ dev: {
8
+ port: 5001,
9
+ },
10
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@easy-editor/materials-dashboard-carousel",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "description": "Carousel component for EasyEditor dashboard",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -45,19 +45,15 @@
45
45
  "@types/react-dom": "^18 || ^19"
46
46
  },
47
47
  "dependencies": {
48
- "@easy-editor/materials-shared": "0.0.0"
48
+ "@easy-editor/materials-shared": "0.0.1"
49
49
  },
50
50
  "scripts": {
51
- "dev": "vite",
51
+ "dev": "easypack dev",
52
52
  "format": "biome format --write .",
53
53
  "lint": "biome check .",
54
54
  "build": "npm-run-all -nl build:*",
55
55
  "build:clean": "rimraf dist/",
56
- "build:js": "rollup -c",
57
- "build:types": "pnpm types",
58
- "types": "npm-run-all -nl types:*",
59
- "types:src": "tsc --project tsconfig.build.json",
60
- "test-types": "tsc --project tsconfig.test.json"
56
+ "build:js": "easypack build"
61
57
  },
62
58
  "module": "dist/index.esm.js",
63
59
  "unpkg": "dist/index.min.js"
package/src/component.tsx CHANGED
@@ -1,174 +1,217 @@
1
- /**
2
- * Carousel Component
3
- * 轮播组件
4
- */
5
-
6
- import { useState, useEffect, useCallback, type CSSProperties, type Ref } from 'react'
7
- import styles from './component.module.css'
8
-
9
- export interface CarouselItem {
10
- /** 图片地址 */
11
- src: string
12
- /** 图片描述 */
13
- alt?: string
14
- /** 点击链接 */
15
- link?: string
16
- }
17
-
18
- export interface CarouselProps {
19
- ref?: Ref<HTMLDivElement>
20
- /** 轮播项 */
21
- items?: CarouselItem[]
22
- /** 自动播放 */
23
- autoPlay?: boolean
24
- /** 自动播放间隔(毫秒) */
25
- interval?: number
26
- /** 是否显示导航按钮 */
27
- showNav?: boolean
28
- /** 是否显示指示器 */
29
- showIndicators?: boolean
30
- /** 是否循环播放 */
31
- loop?: boolean
32
- /** 外部样式 */
33
- style?: CSSProperties
34
- }
35
-
36
- const DEFAULT_ITEMS: CarouselItem[] = [
37
- { src: 'https://picsum.photos/800/400?random=1', alt: 'Slide 1' },
38
- { src: 'https://picsum.photos/800/400?random=2', alt: 'Slide 2' },
39
- { src: 'https://picsum.photos/800/400?random=3', alt: 'Slide 3' },
40
- ]
41
-
42
- const ChevronLeft = () => (
43
- <svg aria-hidden='true' fill='none' height='24' stroke='currentColor' strokeWidth='2' viewBox='0 0 24 24' width='24'>
44
- <title>Previous</title>
45
- <path d='M15 18l-6-6 6-6' />
46
- </svg>
47
- )
48
-
49
- const ChevronRight = () => (
50
- <svg aria-hidden='true' fill='none' height='24' stroke='currentColor' strokeWidth='2' viewBox='0 0 24 24' width='24'>
51
- <title>Next</title>
52
- <path d='M9 18l6-6-6-6' />
53
- </svg>
54
- )
55
-
56
- export const Carousel: React.FC<CarouselProps> = ({
57
- ref,
58
- items = DEFAULT_ITEMS,
59
- autoPlay = true,
60
- interval = 3000,
61
- showNav = true,
62
- showIndicators = true,
63
- loop = true,
64
- style: externalStyle,
65
- }) => {
66
- const [currentIndex, setCurrentIndex] = useState(0)
67
-
68
- const goToNext = useCallback(() => {
69
- setCurrentIndex(prev => {
70
- if (prev >= items.length - 1) {
71
- return loop ? 0 : prev
72
- }
73
- return prev + 1
74
- })
75
- }, [items.length, loop])
76
-
77
- const goToPrev = useCallback(() => {
78
- setCurrentIndex(prev => {
79
- if (prev <= 0) {
80
- return loop ? items.length - 1 : prev
81
- }
82
- return prev - 1
83
- })
84
- }, [items.length, loop])
85
-
86
- const goToSlide = useCallback((index: number) => {
87
- setCurrentIndex(index)
88
- }, [])
89
-
90
- // 自动播放
91
- useEffect(() => {
92
- if (!autoPlay || items.length <= 1) {
93
- return
94
- }
95
-
96
- const timer = setInterval(goToNext, interval)
97
- return () => clearInterval(timer)
98
- }, [autoPlay, interval, goToNext, items.length])
99
-
100
- if (items.length === 0) {
101
- return null
102
- }
103
-
104
- return (
105
- <div className={styles.container} ref={ref} style={externalStyle}>
106
- <div className={styles.track} style={{ transform: `translateX(-${currentIndex * 100}%)` }}>
107
- {items.map((item, index) => (
108
- <div className={styles.slide} key={index}>
109
- {item.link ? (
110
- <a href={item.link} rel='noopener noreferrer' target='_blank'>
111
- <img
112
- alt={item.alt || ''}
113
- className={styles.slideImage}
114
- draggable={false}
115
- height='200'
116
- src={item.src}
117
- width='100%'
118
- />
119
- </a>
120
- ) : (
121
- <img
122
- alt={item.alt || ''}
123
- className={styles.slideImage}
124
- draggable={false}
125
- height='200'
126
- src={item.src}
127
- width='100%'
128
- />
129
- )}
130
- </div>
131
- ))}
132
- </div>
133
-
134
- {/* 导航按钮 */}
135
- {showNav && items.length > 1 && (
136
- <>
137
- <button
138
- aria-label='Previous slide'
139
- className={`${styles.navButton} ${styles.navButtonPrev}`}
140
- onClick={goToPrev}
141
- type='button'
142
- >
143
- <ChevronLeft />
144
- </button>
145
- <button
146
- aria-label='Next slide'
147
- className={`${styles.navButton} ${styles.navButtonNext}`}
148
- onClick={goToNext}
149
- type='button'
150
- >
151
- <ChevronRight />
152
- </button>
153
- </>
154
- )}
155
-
156
- {/* 指示器 */}
157
- {showIndicators && items.length > 1 && (
158
- <div className={styles.indicators}>
159
- {items.map((_, index) => (
160
- <button
161
- aria-label={`Go to slide ${index + 1}`}
162
- className={`${styles.indicator} ${index === currentIndex ? styles.indicatorActive : ''}`}
163
- key={index}
164
- onClick={() => goToSlide(index)}
165
- type='button'
166
- />
167
- ))}
168
- </div>
169
- )}
170
- </div>
171
- )
172
- }
173
-
174
- export default Carousel
1
+ /**
2
+ * Carousel Component
3
+ * 轮播组件 - 支持数据源绑定和事件交互
4
+ */
5
+
6
+ import { useState, useEffect, useCallback, useMemo, type CSSProperties } from 'react'
7
+ import { type MaterialComponet, useDataSource } from '@easy-editor/materials-shared'
8
+ import styles from './component.module.css'
9
+
10
+ export interface CarouselItem {
11
+ /** 图片地址 */
12
+ src: string
13
+ /** 图片描述 */
14
+ alt?: string
15
+ /** 点击链接 */
16
+ link?: string
17
+ }
18
+
19
+ export interface CarouselProps extends MaterialComponet {
20
+ /** 自动播放 */
21
+ autoPlay?: boolean
22
+ /** 自动播放间隔(毫秒) */
23
+ interval?: number
24
+ /** 是否显示导航按钮 */
25
+ showNav?: boolean
26
+ /** 是否显示指示器 */
27
+ showIndicators?: boolean
28
+ /** 是否循环播放 */
29
+ loop?: boolean
30
+ /** 点击事件 */
31
+ onClick?: (e: React.MouseEvent) => void
32
+ /** 双击事件 */
33
+ onDoubleClick?: (e: React.MouseEvent) => void
34
+ /** 鼠标进入 */
35
+ onMouseEnter?: (e: React.MouseEvent) => void
36
+ /** 鼠标离开 */
37
+ onMouseLeave?: (e: React.MouseEvent) => void
38
+ /** 切换事件 */
39
+ onChange?: (index: number) => void
40
+ }
41
+
42
+ const DEFAULT_ITEMS: CarouselItem[] = [
43
+ { src: 'https://picsum.photos/800/400?random=1', alt: 'Slide 1' },
44
+ { src: 'https://picsum.photos/800/400?random=2', alt: 'Slide 2' },
45
+ { src: 'https://picsum.photos/800/400?random=3', alt: 'Slide 3' },
46
+ ]
47
+
48
+ const ChevronLeft = () => (
49
+ <svg aria-hidden='true' fill='none' height='24' stroke='currentColor' strokeWidth='2' viewBox='0 0 24 24' width='24'>
50
+ <title>Previous</title>
51
+ <path d='M15 18l-6-6 6-6' />
52
+ </svg>
53
+ )
54
+
55
+ const ChevronRight = () => (
56
+ <svg aria-hidden='true' fill='none' height='24' stroke='currentColor' strokeWidth='2' viewBox='0 0 24 24' width='24'>
57
+ <title>Next</title>
58
+ <path d='M9 18l6-6-6-6' />
59
+ </svg>
60
+ )
61
+
62
+ export const Carousel: React.FC<CarouselProps> = ({
63
+ ref,
64
+ $data,
65
+ __dataSource,
66
+ autoPlay = true,
67
+ interval = 3000,
68
+ showNav = true,
69
+ showIndicators = true,
70
+ loop = true,
71
+ rotation,
72
+ opacity,
73
+ background,
74
+ style: externalStyle,
75
+ onClick,
76
+ onDoubleClick,
77
+ onMouseEnter,
78
+ onMouseLeave,
79
+ onChange,
80
+ }) => {
81
+ const [currentIndex, setCurrentIndex] = useState(0)
82
+
83
+ // 解析数据源
84
+ const dataSource = useDataSource($data, __dataSource)
85
+ const items = useMemo<CarouselItem[]>(() => {
86
+ if (dataSource.length > 0) {
87
+ return dataSource as CarouselItem[]
88
+ }
89
+ return DEFAULT_ITEMS
90
+ }, [dataSource])
91
+
92
+ const goToNext = useCallback(() => {
93
+ setCurrentIndex(prev => {
94
+ const nextIndex = prev >= items.length - 1 ? (loop ? 0 : prev) : prev + 1
95
+ if (nextIndex !== prev) {
96
+ onChange?.(nextIndex)
97
+ }
98
+ return nextIndex
99
+ })
100
+ }, [items.length, loop, onChange])
101
+
102
+ const goToPrev = useCallback(() => {
103
+ setCurrentIndex(prev => {
104
+ const nextIndex = prev <= 0 ? (loop ? items.length - 1 : prev) : prev - 1
105
+ if (nextIndex !== prev) {
106
+ onChange?.(nextIndex)
107
+ }
108
+ return nextIndex
109
+ })
110
+ }, [items.length, loop, onChange])
111
+
112
+ const goToSlide = useCallback(
113
+ (index: number) => {
114
+ setCurrentIndex(index)
115
+ onChange?.(index)
116
+ },
117
+ [onChange],
118
+ )
119
+
120
+ // 自动播放
121
+ useEffect(() => {
122
+ if (!autoPlay || items.length <= 1) {
123
+ return
124
+ }
125
+
126
+ const timer = setInterval(goToNext, interval)
127
+ return () => clearInterval(timer)
128
+ }, [autoPlay, interval, goToNext, items.length])
129
+
130
+ if (items.length === 0) {
131
+ return null
132
+ }
133
+
134
+ const containerStyle: CSSProperties = {
135
+ transform: rotation ? `rotate(${rotation}deg)` : undefined,
136
+ opacity: opacity !== undefined ? opacity / 100 : undefined,
137
+ backgroundColor: background,
138
+ ...externalStyle,
139
+ }
140
+
141
+ return (
142
+ <div
143
+ className={styles.container}
144
+ onClick={onClick}
145
+ onDoubleClick={onDoubleClick}
146
+ onMouseEnter={onMouseEnter}
147
+ onMouseLeave={onMouseLeave}
148
+ ref={ref}
149
+ style={containerStyle}
150
+ >
151
+ <div className={styles.track} style={{ transform: `translateX(-${currentIndex * 100}%)` }}>
152
+ {items.map((item, index) => (
153
+ <div className={styles.slide} key={index}>
154
+ {item.link ? (
155
+ <a href={item.link} rel='noopener noreferrer' target='_blank'>
156
+ <img
157
+ alt={item.alt || ''}
158
+ className={styles.slideImage}
159
+ draggable={false}
160
+ height='200'
161
+ src={item.src}
162
+ width='100%'
163
+ />
164
+ </a>
165
+ ) : (
166
+ <img
167
+ alt={item.alt || ''}
168
+ className={styles.slideImage}
169
+ draggable={false}
170
+ height='200'
171
+ src={item.src}
172
+ width='100%'
173
+ />
174
+ )}
175
+ </div>
176
+ ))}
177
+ </div>
178
+
179
+ {/* 导航按钮 */}
180
+ {showNav && items.length > 1 && (
181
+ <>
182
+ <button
183
+ aria-label='Previous slide'
184
+ className={`${styles.navButton} ${styles.navButtonPrev}`}
185
+ onClick={goToPrev}
186
+ type='button'
187
+ >
188
+ <ChevronLeft />
189
+ </button>
190
+ <button
191
+ aria-label='Next slide'
192
+ className={`${styles.navButton} ${styles.navButtonNext}`}
193
+ onClick={goToNext}
194
+ type='button'
195
+ >
196
+ <ChevronRight />
197
+ </button>
198
+ </>
199
+ )}
200
+
201
+ {/* 指示器 */}
202
+ {showIndicators && items.length > 1 && (
203
+ <div className={styles.indicators}>
204
+ {items.map((_, index) => (
205
+ <button
206
+ aria-label={`Go to slide ${index + 1}`}
207
+ className={`${styles.indicator} ${index === currentIndex ? styles.indicatorActive : ''}`}
208
+ key={index}
209
+ onClick={() => goToSlide(index)}
210
+ type='button'
211
+ />
212
+ ))}
213
+ </div>
214
+ )}
215
+ </div>
216
+ )
217
+ }