@ably/ui 16.1.2-dev.7eaf96b5 → 16.1.2-dev.8dee7a5e

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/core/Flash.js CHANGED
@@ -1,2 +1,2 @@
1
- import React,{useEffect,useState,useRef}from"react";import DOMPurify from"dompurify";import{getRemoteDataStore}from"./remote-data-store.js";import ConnectStateWrapper from"./ConnectStateWrapper";import Icon from"./Icon";const REDUCER_KEY="flashes";const FLASH_DATA_ID="ui-flashes";const initialState={items:[]};const reducerFlashes={[REDUCER_KEY]:(state=initialState,action)=>{switch(action.type){case"flash/push":{const flashes=Array.isArray(action.payload)?action.payload:[action.payload];return{items:[...state.items,...flashes]}}default:return state}}};const selectFlashes=store=>store.getState()[REDUCER_KEY];const FLASH_BG_COLOR={error:"bg-gui-error",success:"bg-zingy-green",notice:"bg-electric-cyan",info:"bg-electric-cyan",alert:"bg-active-orange"};const FLASH_TEXT_COLOR={error:"text-white",success:"text-cool-black",notice:"text-cool-black",info:"text-cool-black",alert:"text-white"};const AUTO_HIDE=["success","info","notice"];const AUTO_HIDE_TIME=8e3;const useAutoHide=(type,closeFlash)=>{const timeoutId=useRef(null);useEffect(()=>{if(AUTO_HIDE.includes(type)){timeoutId.current=setTimeout(()=>{closeFlash()},AUTO_HIDE_TIME)}return()=>{if(timeoutId.current){clearTimeout(timeoutId.current)}}},[])};const Flash=({id,type,content,removeFlash})=>{const ref=useRef(null);const[closed,setClosed]=useState(false);const[flashHeight,setFlashHeight]=useState(0);const[triggerEntryAnimation,setTriggerEntryAnimation]=useState(false);const closeFlash=()=>{if(ref.current){setFlashHeight(ref.current.getBoundingClientRect().height)}setClosed(true);setTimeout(()=>{if(id){removeFlash(id)}},100)};useEffect(()=>setTriggerEntryAnimation(true),[]);useAutoHide(type,closeFlash);const animateEntry=triggerEntryAnimation&&!closed;let style;if(flashHeight&&!closed){style={height:`${flashHeight}px`}}else if(closed){style={height:0,marginTop:0,zIndex:-1}}else{style={}}const safeContent=DOMPurify.sanitize(content,{ALLOWED_TAGS:["a"],ALLOWED_ATTR:["href","data-method","rel"]});const withIcons={notice:"icon-gui-ably-badge",success:"icon-gui-check-outline",error:"icon-gui-exclamation-triangle-outline",alert:"icon-gui-exclamation-triangle-outline",info:""};const iconColor={notice:"text-cool-black",success:"text-cool-black",error:"text-white",alert:"text-white",info:""};return React.createElement("div",{className:`ui-flash-message ui-grid-px ${animateEntry?"ui-flash-message-enter":""}`,style:style,ref:ref,"data-id":"ui-flash"},React.createElement("div",{className:`${FLASH_BG_COLOR[type]} p-32 flex align-center rounded shadow-container-subtle`},withIcons[type]&&iconColor[type]&&React.createElement(Icon,{name:withIcons[type],color:iconColor[type],size:"1.5rem",additionalCSS:"mr-16 self-baseline"}),React.createElement("p",{className:`ui-text-p1 mr-16 ${FLASH_TEXT_COLOR[type]}`,dangerouslySetInnerHTML:{__html:safeContent}}),React.createElement("button",{type:"button",className:"p-0 ml-auto self-start focus:outline-none",onClick:closeFlash},iconColor[type]&&React.createElement(Icon,{name:"icon-gui-x-mark-outline",color:iconColor[type],size:"1.5rem",additionalCSS:"transition-colors"}))))};const Flashes=({flashes})=>{const[flashesWithIds,setFlashesWithIds]=useState([]);const removeFlash=flashId=>setFlashesWithIds(items=>items.filter(item=>item.id!==flashId));useEffect(()=>{setFlashesWithIds(state=>{return[...state,...(flashes?.items??[]).map(flash=>({...flash,id:Math.random().toString(36).slice(2),removed:false}))]})},[flashes]);return React.createElement("div",{className:"ui-flash","data-id":FLASH_DATA_ID},flashesWithIds.filter(item=>!item.removed).map(flash=>React.createElement(Flash,{key:flash.id,...flash,removeFlash:removeFlash})))};const BackendFlashes=({flashes})=>{useEffect(()=>{const transformedFlashes=flashes.map(flash=>{const[type,content]=flash;return{type,content}})||[];if(transformedFlashes.length>0){const store=getRemoteDataStore();store.dispatch({type:"flash/push",payload:transformedFlashes})}},[]);const WrappedFlashes=ConnectStateWrapper(Flashes,{flashes:selectFlashes});return React.createElement(WrappedFlashes,null)};export{reducerFlashes,FLASH_DATA_ID,Flashes};export default BackendFlashes;
1
+ import React,{useEffect,useState,useRef}from"react";import DOMPurify from"dompurify";import{getRemoteDataStore}from"./remote-data-store.js";import ConnectStateWrapper from"./ConnectStateWrapper";import Icon from"./Icon";const REDUCER_KEY="flashes";const FLASH_DATA_ID="ui-flashes";const initialState={items:[]};const reducerFlashes={[REDUCER_KEY]:(state=initialState,action)=>{switch(action.type){case"flash/push":{const flashes=Array.isArray(action.payload)?action.payload:[action.payload];return{items:[...state.items,...flashes]}}default:return state}}};const selectFlashes=store=>store.getState()[REDUCER_KEY];const FLASH_BG_COLOR={error:"bg-gui-error",success:"bg-zingy-green",notice:"bg-electric-cyan",info:"bg-electric-cyan",alert:"bg-active-orange"};const FLASH_TEXT_COLOR={error:"text-white",success:"text-cool-black",notice:"text-cool-black",info:"text-cool-black",alert:"text-white"};const AUTO_HIDE=["success","info","notice"];const AUTO_HIDE_TIME=8e3;const useAutoHide=(type,closeFlash)=>{const timeoutId=useRef(null);useEffect(()=>{if(AUTO_HIDE.includes(type)){timeoutId.current=setTimeout(()=>{closeFlash()},AUTO_HIDE_TIME)}return()=>{if(timeoutId.current){clearTimeout(timeoutId.current)}}},[])};const Flash=({id,type,content,removeFlash})=>{const ref=useRef(null);const[closed,setClosed]=useState(false);const[flashHeight,setFlashHeight]=useState(0);const[triggerEntryAnimation,setTriggerEntryAnimation]=useState(false);const closeFlash=()=>{if(ref.current){setFlashHeight(ref.current.getBoundingClientRect().height)}setClosed(true);setTimeout(()=>{if(id){removeFlash(id)}},100)};useEffect(()=>setTriggerEntryAnimation(true),[]);useAutoHide(type,closeFlash);const animateEntry=triggerEntryAnimation&&!closed;let style;if(flashHeight&&!closed){style={height:`${flashHeight}px`}}else if(closed){style={height:0,marginTop:0,zIndex:-1}}else{style={}}const safeContent=DOMPurify.sanitize(content,{ALLOWED_TAGS:["a"],ALLOWED_ATTR:["href","data-method"],ALLOWED_URI_REGEXP:/^\/[^/]/});const withIcons={notice:"icon-gui-ably-badge",success:"icon-gui-check-outline",error:"icon-gui-exclamation-triangle-outline",alert:"icon-gui-exclamation-triangle-outline",info:""};const iconColor={notice:"text-cool-black",success:"text-cool-black",error:"text-white",alert:"text-white",info:""};return React.createElement("div",{className:`ui-flash-message ui-grid-px ${animateEntry?"ui-flash-message-enter":""}`,style:style,ref:ref,"data-id":"ui-flash","data-testid":"ui-flash"},React.createElement("div",{className:`${FLASH_BG_COLOR[type]} p-32 flex align-center rounded shadow-container-subtle`},withIcons[type]&&iconColor[type]&&React.createElement(Icon,{name:withIcons[type],color:iconColor[type],size:"1.5rem",additionalCSS:"mr-16 self-baseline"}),React.createElement("p",{className:`ui-text-p1 mr-16 ${FLASH_TEXT_COLOR[type]}`,dangerouslySetInnerHTML:{__html:safeContent}}),React.createElement("button",{type:"button",className:"p-0 ml-auto self-start focus:outline-none",onClick:closeFlash},iconColor[type]&&React.createElement(Icon,{name:"icon-gui-x-mark-outline",color:iconColor[type],size:"1.5rem",additionalCSS:"transition-colors"}))))};const Flashes=({flashes})=>{const[flashesWithIds,setFlashesWithIds]=useState([]);const removeFlash=flashId=>setFlashesWithIds(items=>items.filter(item=>item.id!==flashId));useEffect(()=>{setFlashesWithIds(state=>{return[...state,...(flashes?.items??[]).map(flash=>({...flash,id:Math.random().toString(36).slice(2),removed:false,removeFlash}))]})},[flashes]);return React.createElement("div",{className:"ui-flash","data-id":FLASH_DATA_ID},flashesWithIds.filter(item=>!item.removed).map(flash=>React.createElement(Flash,{key:flash.id,...flash})))};const BackendFlashes=({flashes})=>{useEffect(()=>{const transformedFlashes=flashes.map(flash=>{const[type,content]=flash;return{type,content}})||[];if(transformedFlashes.length>0){const store=getRemoteDataStore();store.dispatch({type:"flash/push",payload:transformedFlashes})}},[]);const WrappedFlashes=ConnectStateWrapper(Flashes,{flashes:selectFlashes});return React.createElement(WrappedFlashes,null)};export{reducerFlashes,FLASH_DATA_ID,Flashes};export default BackendFlashes;
2
2
  //# sourceMappingURL=Flash.js.map
package/core/Flash.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/Flash.tsx"],"sourcesContent":["import React, { useEffect, useState, useRef } from \"react\";\nimport DOMPurify from \"dompurify\";\nimport { getRemoteDataStore } from \"./remote-data-store.js\";\nimport ConnectStateWrapper from \"./ConnectStateWrapper\";\nimport Icon from \"./Icon\";\nimport { ColorClass } from \"./styles/colors/types\";\nimport { IconName } from \"./Icon/types\";\n\ntype FlashPropsType = \"error\" | \"success\" | \"notice\" | \"info\" | \"alert\";\n\ntype FlashProps = {\n id: string;\n removed: boolean;\n type: FlashPropsType;\n content: string;\n removeFlash: (id: string) => void;\n};\n\ntype FlashesProps = {\n flashes: { items: FlashProps[] };\n};\n\ntype BackendFlashesProps = {\n flashes: string[][];\n};\n\nconst REDUCER_KEY = \"flashes\";\nconst FLASH_DATA_ID = \"ui-flashes\";\n\nconst initialState = { items: [] };\n\nconst reducerFlashes = {\n [REDUCER_KEY]: (\n state: {\n items: FlashProps[];\n } = initialState,\n action: { type: string; payload: FlashProps | FlashProps[] },\n ) => {\n switch (action.type) {\n case \"flash/push\": {\n const flashes = Array.isArray(action.payload)\n ? action.payload\n : [action.payload];\n return { items: [...state.items, ...flashes] };\n }\n default:\n return state;\n }\n },\n};\n\n// Not cool but redux isn't a long term plan here\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst selectFlashes = (store: any): { items: FlashProps[] } =>\n store.getState()[REDUCER_KEY];\n\nconst FLASH_BG_COLOR = {\n error: \"bg-gui-error\",\n success: \"bg-zingy-green\",\n notice: \"bg-electric-cyan\",\n info: \"bg-electric-cyan\",\n alert: \"bg-active-orange\",\n};\n\nconst FLASH_TEXT_COLOR = {\n error: \"text-white\",\n success: \"text-cool-black\",\n notice: \"text-cool-black\",\n info: \"text-cool-black\",\n alert: \"text-white\",\n};\n\nconst AUTO_HIDE = [\"success\", \"info\", \"notice\"];\nconst AUTO_HIDE_TIME = 8000;\n\nconst useAutoHide = (type: string, closeFlash: () => void) => {\n const timeoutId = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n useEffect(() => {\n if (AUTO_HIDE.includes(type)) {\n timeoutId.current = setTimeout(() => {\n closeFlash();\n }, AUTO_HIDE_TIME);\n }\n\n return () => {\n if (timeoutId.current) {\n clearTimeout(timeoutId.current);\n }\n };\n }, []);\n};\n\nconst Flash = ({ id, type, content, removeFlash }: FlashProps) => {\n const ref = useRef<HTMLDivElement>(null);\n const [closed, setClosed] = useState(false);\n const [flashHeight, setFlashHeight] = useState(0);\n const [triggerEntryAnimation, setTriggerEntryAnimation] = useState(false);\n\n const closeFlash = () => {\n if (ref.current) {\n setFlashHeight(ref.current.getBoundingClientRect().height);\n }\n\n setClosed(true);\n\n setTimeout(() => {\n if (id) {\n removeFlash(id);\n }\n }, 100);\n };\n\n useEffect(() => setTriggerEntryAnimation(true), []);\n useAutoHide(type, closeFlash);\n\n const animateEntry = triggerEntryAnimation && !closed;\n\n let style;\n\n if (flashHeight && !closed) {\n style = { height: `${flashHeight}px` };\n } else if (closed) {\n style = { height: 0, marginTop: 0, zIndex: -1 };\n } else {\n style = {};\n }\n\n const safeContent = DOMPurify.sanitize(content, {\n ALLOWED_TAGS: [\"a\"],\n ALLOWED_ATTR: [\"href\", \"data-method\", \"rel\"],\n });\n\n const withIcons: Record<FlashPropsType, IconName | \"\"> = {\n notice: \"icon-gui-ably-badge\",\n success: \"icon-gui-check-outline\",\n error: \"icon-gui-exclamation-triangle-outline\",\n alert: \"icon-gui-exclamation-triangle-outline\",\n info: \"\",\n };\n\n const iconColor: Record<FlashPropsType, ColorClass | \"\"> = {\n notice: \"text-cool-black\",\n success: \"text-cool-black\",\n error: \"text-white\",\n alert: \"text-white\",\n info: \"\",\n };\n\n return (\n <div\n className={`ui-flash-message ui-grid-px ${\n animateEntry ? \"ui-flash-message-enter\" : \"\"\n }`}\n style={style}\n ref={ref}\n data-id=\"ui-flash\"\n >\n <div\n className={`${FLASH_BG_COLOR[type]} p-32 flex align-center rounded shadow-container-subtle`}\n >\n {withIcons[type] && iconColor[type] && (\n <Icon\n name={withIcons[type]}\n color={iconColor[type]}\n size=\"1.5rem\"\n additionalCSS=\"mr-16 self-baseline\"\n />\n )}\n <p\n className={`ui-text-p1 mr-16 ${FLASH_TEXT_COLOR[type]}`}\n dangerouslySetInnerHTML={{ __html: safeContent }}\n />\n <button\n type=\"button\"\n className=\"p-0 ml-auto self-start focus:outline-none\"\n onClick={closeFlash}\n >\n {iconColor[type] && (\n <Icon\n name=\"icon-gui-x-mark-outline\"\n color={iconColor[type]}\n size=\"1.5rem\"\n additionalCSS=\"transition-colors\"\n />\n )}\n </button>\n </div>\n </div>\n );\n};\n\nconst Flashes = ({ flashes }: FlashesProps) => {\n const [flashesWithIds, setFlashesWithIds] = useState<FlashProps[]>([]);\n\n const removeFlash = (flashId: string) =>\n setFlashesWithIds((items) => items.filter((item) => item.id !== flashId));\n\n useEffect(() => {\n setFlashesWithIds((state) => {\n return [\n ...state,\n ...(flashes?.items ?? []).map((flash) => ({\n ...flash,\n id: Math.random().toString(36).slice(2),\n removed: false,\n })),\n ];\n });\n }, [flashes]);\n\n return (\n <div className=\"ui-flash\" data-id={FLASH_DATA_ID}>\n {flashesWithIds\n .filter((item) => !item.removed)\n .map((flash) => (\n <Flash key={flash.id} {...flash} removeFlash={removeFlash} />\n ))}\n </div>\n );\n};\n\nconst BackendFlashes = ({ flashes }: BackendFlashesProps) => {\n useEffect(() => {\n const transformedFlashes =\n flashes.map((flash) => {\n const [type, content] = flash;\n return { type, content };\n }) || [];\n\n if (transformedFlashes.length > 0) {\n const store = getRemoteDataStore();\n\n store.dispatch({\n type: \"flash/push\",\n payload: transformedFlashes,\n });\n }\n }, []);\n\n const WrappedFlashes = ConnectStateWrapper(Flashes, {\n flashes: selectFlashes,\n });\n\n return <WrappedFlashes />;\n};\n\nexport { reducerFlashes, FLASH_DATA_ID, Flashes };\nexport default BackendFlashes;\n"],"names":["React","useEffect","useState","useRef","DOMPurify","getRemoteDataStore","ConnectStateWrapper","Icon","REDUCER_KEY","FLASH_DATA_ID","initialState","items","reducerFlashes","state","action","type","flashes","Array","isArray","payload","selectFlashes","store","getState","FLASH_BG_COLOR","error","success","notice","info","alert","FLASH_TEXT_COLOR","AUTO_HIDE","AUTO_HIDE_TIME","useAutoHide","closeFlash","timeoutId","includes","current","setTimeout","clearTimeout","Flash","id","content","removeFlash","ref","closed","setClosed","flashHeight","setFlashHeight","triggerEntryAnimation","setTriggerEntryAnimation","getBoundingClientRect","height","animateEntry","style","marginTop","zIndex","safeContent","sanitize","ALLOWED_TAGS","ALLOWED_ATTR","withIcons","iconColor","div","className","data-id","name","color","size","additionalCSS","p","dangerouslySetInnerHTML","__html","button","onClick","Flashes","flashesWithIds","setFlashesWithIds","flashId","filter","item","map","flash","Math","random","toString","slice","removed","key","BackendFlashes","transformedFlashes","length","dispatch","WrappedFlashes"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/core/Flash.tsx"],"sourcesContent":["import React, { useEffect, useState, useRef } from \"react\";\nimport DOMPurify from \"dompurify\";\nimport { getRemoteDataStore } from \"./remote-data-store.js\";\nimport ConnectStateWrapper from \"./ConnectStateWrapper\";\nimport Icon from \"./Icon\";\nimport { ColorClass } from \"./styles/colors/types\";\nimport { IconName } from \"./Icon/types\";\n\ntype FlashPropsType = \"error\" | \"success\" | \"notice\" | \"info\" | \"alert\";\n\ntype FlashProps = {\n id: string;\n removed: boolean;\n type: FlashPropsType;\n content: string;\n removeFlash: (id: string) => void;\n};\n\ntype FlashesProps = {\n flashes: { items: Pick<FlashProps, \"type\" | \"content\">[] };\n};\n\ntype BackendFlashesProps = {\n flashes: string[][];\n};\n\nconst REDUCER_KEY = \"flashes\";\nconst FLASH_DATA_ID = \"ui-flashes\";\n\nconst initialState = { items: [] };\n\nconst reducerFlashes = {\n [REDUCER_KEY]: (\n state: {\n items: FlashProps[];\n } = initialState,\n action: { type: string; payload: FlashProps | FlashProps[] },\n ) => {\n switch (action.type) {\n case \"flash/push\": {\n const flashes = Array.isArray(action.payload)\n ? action.payload\n : [action.payload];\n return { items: [...state.items, ...flashes] };\n }\n default:\n return state;\n }\n },\n};\n\n// Not cool but redux isn't a long term plan here\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst selectFlashes = (store: any): { items: FlashProps[] } =>\n store.getState()[REDUCER_KEY];\n\nconst FLASH_BG_COLOR = {\n error: \"bg-gui-error\",\n success: \"bg-zingy-green\",\n notice: \"bg-electric-cyan\",\n info: \"bg-electric-cyan\",\n alert: \"bg-active-orange\",\n};\n\nconst FLASH_TEXT_COLOR = {\n error: \"text-white\",\n success: \"text-cool-black\",\n notice: \"text-cool-black\",\n info: \"text-cool-black\",\n alert: \"text-white\",\n};\n\nconst AUTO_HIDE = [\"success\", \"info\", \"notice\"];\nconst AUTO_HIDE_TIME = 8000;\n\nconst useAutoHide = (type: string, closeFlash: () => void) => {\n const timeoutId = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n useEffect(() => {\n if (AUTO_HIDE.includes(type)) {\n timeoutId.current = setTimeout(() => {\n closeFlash();\n }, AUTO_HIDE_TIME);\n }\n\n return () => {\n if (timeoutId.current) {\n clearTimeout(timeoutId.current);\n }\n };\n }, []);\n};\n\nconst Flash = ({ id, type, content, removeFlash }: FlashProps) => {\n const ref = useRef<HTMLDivElement>(null);\n const [closed, setClosed] = useState(false);\n const [flashHeight, setFlashHeight] = useState(0);\n const [triggerEntryAnimation, setTriggerEntryAnimation] = useState(false);\n\n const closeFlash = () => {\n if (ref.current) {\n setFlashHeight(ref.current.getBoundingClientRect().height);\n }\n\n setClosed(true);\n\n setTimeout(() => {\n if (id) {\n removeFlash(id);\n }\n }, 100);\n };\n\n useEffect(() => setTriggerEntryAnimation(true), []);\n useAutoHide(type, closeFlash);\n\n const animateEntry = triggerEntryAnimation && !closed;\n\n let style;\n\n if (flashHeight && !closed) {\n style = { height: `${flashHeight}px` };\n } else if (closed) {\n style = { height: 0, marginTop: 0, zIndex: -1 };\n } else {\n style = {};\n }\n\n const safeContent = DOMPurify.sanitize(content, {\n ALLOWED_TAGS: [\"a\"],\n ALLOWED_ATTR: [\"href\", \"data-method\"],\n ALLOWED_URI_REGEXP: /^\\/[^/]/,\n });\n\n const withIcons: Record<FlashPropsType, IconName | \"\"> = {\n notice: \"icon-gui-ably-badge\",\n success: \"icon-gui-check-outline\",\n error: \"icon-gui-exclamation-triangle-outline\",\n alert: \"icon-gui-exclamation-triangle-outline\",\n info: \"\",\n };\n\n const iconColor: Record<FlashPropsType, ColorClass | \"\"> = {\n notice: \"text-cool-black\",\n success: \"text-cool-black\",\n error: \"text-white\",\n alert: \"text-white\",\n info: \"\",\n };\n\n return (\n <div\n className={`ui-flash-message ui-grid-px ${\n animateEntry ? \"ui-flash-message-enter\" : \"\"\n }`}\n style={style}\n ref={ref}\n data-id=\"ui-flash\"\n data-testid=\"ui-flash\"\n >\n <div\n className={`${FLASH_BG_COLOR[type]} p-32 flex align-center rounded shadow-container-subtle`}\n >\n {withIcons[type] && iconColor[type] && (\n <Icon\n name={withIcons[type]}\n color={iconColor[type]}\n size=\"1.5rem\"\n additionalCSS=\"mr-16 self-baseline\"\n />\n )}\n <p\n className={`ui-text-p1 mr-16 ${FLASH_TEXT_COLOR[type]}`}\n dangerouslySetInnerHTML={{ __html: safeContent }}\n />\n <button\n type=\"button\"\n className=\"p-0 ml-auto self-start focus:outline-none\"\n onClick={closeFlash}\n >\n {iconColor[type] && (\n <Icon\n name=\"icon-gui-x-mark-outline\"\n color={iconColor[type]}\n size=\"1.5rem\"\n additionalCSS=\"transition-colors\"\n />\n )}\n </button>\n </div>\n </div>\n );\n};\n\nconst Flashes = ({ flashes }: FlashesProps) => {\n const [flashesWithIds, setFlashesWithIds] = useState<FlashProps[]>([]);\n\n const removeFlash = (flashId: string) =>\n setFlashesWithIds((items) => items.filter((item) => item.id !== flashId));\n\n useEffect(() => {\n setFlashesWithIds((state) => {\n return [\n ...state,\n ...(flashes?.items ?? []).map((flash) => ({\n ...flash,\n id: Math.random().toString(36).slice(2),\n removed: false,\n removeFlash,\n })),\n ];\n });\n }, [flashes]);\n\n return (\n <div className=\"ui-flash\" data-id={FLASH_DATA_ID}>\n {flashesWithIds\n .filter((item) => !item.removed)\n .map((flash) => (\n <Flash key={flash.id} {...flash} />\n ))}\n </div>\n );\n};\n\nconst BackendFlashes = ({ flashes }: BackendFlashesProps) => {\n useEffect(() => {\n const transformedFlashes =\n flashes.map((flash) => {\n const [type, content] = flash;\n return { type, content };\n }) || [];\n\n if (transformedFlashes.length > 0) {\n const store = getRemoteDataStore();\n\n store.dispatch({\n type: \"flash/push\",\n payload: transformedFlashes,\n });\n }\n }, []);\n\n const WrappedFlashes = ConnectStateWrapper(Flashes, {\n flashes: selectFlashes,\n });\n\n return <WrappedFlashes />;\n};\n\nexport { reducerFlashes, FLASH_DATA_ID, Flashes };\nexport default BackendFlashes;\n"],"names":["React","useEffect","useState","useRef","DOMPurify","getRemoteDataStore","ConnectStateWrapper","Icon","REDUCER_KEY","FLASH_DATA_ID","initialState","items","reducerFlashes","state","action","type","flashes","Array","isArray","payload","selectFlashes","store","getState","FLASH_BG_COLOR","error","success","notice","info","alert","FLASH_TEXT_COLOR","AUTO_HIDE","AUTO_HIDE_TIME","useAutoHide","closeFlash","timeoutId","includes","current","setTimeout","clearTimeout","Flash","id","content","removeFlash","ref","closed","setClosed","flashHeight","setFlashHeight","triggerEntryAnimation","setTriggerEntryAnimation","getBoundingClientRect","height","animateEntry","style","marginTop","zIndex","safeContent","sanitize","ALLOWED_TAGS","ALLOWED_ATTR","ALLOWED_URI_REGEXP","withIcons","iconColor","div","className","data-id","data-testid","name","color","size","additionalCSS","p","dangerouslySetInnerHTML","__html","button","onClick","Flashes","flashesWithIds","setFlashesWithIds","flashId","filter","item","map","flash","Math","random","toString","slice","removed","key","BackendFlashes","transformedFlashes","length","dispatch","WrappedFlashes"],"mappings":"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"}
package/core/Notice.js CHANGED
@@ -1,2 +1,2 @@
1
- import React,{useEffect}from"react";import Icon from"./Icon";import cn from"./utils/cn.js";import NoticeScripts from"./Notice/component.js";const defaultTextColor="text-neutral-1300 dark:text-neutral-000";const contentWrapperClasses="w-full pr-8 ui-text-p4 self-center";const ContentWrapper=({buttonLink,textColor=defaultTextColor,children})=>buttonLink?React.createElement("a",{href:buttonLink,className:cn(contentWrapperClasses,textColor)},children):React.createElement("div",{className:cn(contentWrapperClasses,textColor)},children);const Notice=({buttonLink,buttonLabel,bodyText,title,config,closeBtn,bgColor="bg-orange-100 dark:bg-orange-1100",textColor=defaultTextColor})=>{useEffect(()=>{NoticeScripts({bannerContainer:document.querySelector('[data-id="ui-notice"]'),cookieId:config?.cookieId,noticeId:config?.noticeId,options:{collapse:config?.options?.collapse||false}})},[]);return React.createElement("div",{className:cn("ui-announcement",bgColor,textColor),"data-id":"ui-notice",style:{maxHeight:0,overflow:"hidden"}},React.createElement("div",{className:"ui-grid-px py-16 max-w-screen-xl mx-auto flex items-start"},React.createElement(ContentWrapper,{buttonLink:buttonLink??"#"},React.createElement("strong",{className:"font-bold whitespace-nowrap pr-4"},title),React.createElement("span",{className:"pr-4"},bodyText),buttonLabel&&React.createElement("span",{className:"cursor-pointer whitespace-nowrap text-gui-blue-default-light dark:text-gui-blue-default-dark"},buttonLabel)),closeBtn&&React.createElement("button",{type:"button",className:"ml-auto h-20 w-20 border-none bg-none self-baseline"},React.createElement(Icon,{name:"icon-gui-x-mark-outline",size:"1.25rem",color:textColor}))))};export default Notice;
1
+ import React,{useEffect,useRef}from"react";import DOMPurify from"dompurify";import Icon from"./Icon";import cn from"./utils/cn.js";import NoticeScripts from"./Notice/component.js";import useRailsUjsLinks from"./hooks/use-rails-ujs-hooks";const defaultTextColor="text-neutral-1300 dark:text-neutral-000";const contentWrapperClasses="w-full pr-8 ui-text-p4 self-center";const ContentWrapper=({buttonLink,textColor=defaultTextColor,children})=>buttonLink?React.createElement("a",{href:buttonLink,className:cn(contentWrapperClasses,textColor)},children):React.createElement("div",{className:cn(contentWrapperClasses,textColor)},children);const Notice=({buttonLink,buttonLabel,bodyText,title,config,closeBtn,bgColor="bg-orange-100 dark:bg-orange-1100",textColor=defaultTextColor})=>{const contentRef=useRef(null);useRailsUjsLinks(contentRef);useEffect(()=>{NoticeScripts({bannerContainer:document.querySelector('[data-id="ui-notice"]'),cookieId:config?.cookieId,noticeId:config?.noticeId,options:{collapse:config?.options?.collapse||false}})},[config?.cookieId,config?.noticeId,config?.options?.collapse]);const safeContent=DOMPurify.sanitize(bodyText??"",{ALLOWED_TAGS:["a"],ALLOWED_ATTR:["href","data-method"],ALLOWED_URI_REGEXP:/^\/[^/]/});return React.createElement("div",{className:cn("ui-announcement",bgColor,textColor),"data-id":"ui-notice",style:{maxHeight:0,overflow:"hidden"}},React.createElement("div",{className:"ui-grid-px py-16 max-w-screen-xl mx-auto flex items-start"},React.createElement(ContentWrapper,{buttonLink:buttonLink??"#"},React.createElement("strong",{className:"font-bold whitespace-nowrap pr-4"},title),React.createElement("span",{ref:contentRef,className:"pr-4",dangerouslySetInnerHTML:{__html:safeContent}}),buttonLabel&&React.createElement("span",{className:"cursor-pointer whitespace-nowrap text-gui-blue-default-light dark:text-gui-blue-default-dark"},buttonLabel)),closeBtn&&React.createElement("button",{type:"button",className:"ml-auto h-20 w-20 border-none bg-none self-baseline"},React.createElement(Icon,{name:"icon-gui-x-mark-outline",size:"1.25rem",color:textColor}))))};export default Notice;
2
2
  //# sourceMappingURL=Notice.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/Notice.tsx"],"sourcesContent":["import React, { ReactNode, useEffect } from \"react\";\n\nimport { ColorClass, ColorThemeSet } from \"./styles/colors/types\";\nimport Icon from \"./Icon\";\nimport cn from \"./utils/cn.js\";\nimport NoticeScripts from \"./Notice/component.js\";\n\ntype ContentWrapperProps = {\n buttonLink: string;\n children: ReactNode;\n textColor?: ColorClass | ColorThemeSet;\n};\n\n// TODO(jamiehenson):\n// This type is a bit messed up currently due to the NoticeScripts import being interpreted as NoticeProps.\n// Plan is to TS-ify the JS assets too, so this can be rectified then. The NoticeScripts-oriented props are\n// the ones after the line break.\nexport type NoticeProps = {\n buttonLink?: string;\n buttonLabel?: string;\n bodyText?: string;\n title?: string;\n closeBtn?: boolean;\n config?: {\n options: {\n collapse: boolean;\n };\n noticeId: string | number;\n cookieId: string;\n };\n bgColor?: string;\n textColor?: ColorClass | ColorThemeSet;\n\n bannerContainer?: Element | null;\n cookieId?: string;\n noticeId?: string;\n options?: { collapse: boolean };\n};\n\nconst defaultTextColor = \"text-neutral-1300 dark:text-neutral-000\";\n\nconst contentWrapperClasses = \"w-full pr-8 ui-text-p4 self-center\";\n\nconst ContentWrapper = ({\n buttonLink,\n textColor = defaultTextColor,\n children,\n}: ContentWrapperProps) =>\n buttonLink ? (\n <a href={buttonLink} className={cn(contentWrapperClasses, textColor)}>\n {children}\n </a>\n ) : (\n <div className={cn(contentWrapperClasses, textColor)}>{children}</div>\n );\n\nconst Notice = ({\n buttonLink,\n buttonLabel,\n bodyText,\n title,\n config,\n closeBtn,\n bgColor = \"bg-orange-100 dark:bg-orange-1100\",\n textColor = defaultTextColor,\n}: NoticeProps) => {\n useEffect(() => {\n NoticeScripts({\n bannerContainer: document.querySelector('[data-id=\"ui-notice\"]'),\n cookieId: config?.cookieId,\n noticeId: config?.noticeId,\n options: {\n collapse: config?.options?.collapse || false,\n },\n });\n }, []);\n\n return (\n <div\n className={cn(\"ui-announcement\", bgColor, textColor)}\n data-id=\"ui-notice\"\n style={{ maxHeight: 0, overflow: \"hidden\" }}\n >\n <div className=\"ui-grid-px py-16 max-w-screen-xl mx-auto flex items-start\">\n <ContentWrapper buttonLink={buttonLink ?? \"#\"}>\n <strong className=\"font-bold whitespace-nowrap pr-4\">{title}</strong>\n <span className=\"pr-4\">{bodyText}</span>\n {buttonLabel && (\n <span className=\"cursor-pointer whitespace-nowrap text-gui-blue-default-light dark:text-gui-blue-default-dark\">\n {buttonLabel}\n </span>\n )}\n </ContentWrapper>\n\n {closeBtn && (\n <button\n type=\"button\"\n className=\"ml-auto h-20 w-20 border-none bg-none self-baseline\"\n >\n <Icon\n name=\"icon-gui-x-mark-outline\"\n size=\"1.25rem\"\n color={textColor}\n />\n </button>\n )}\n </div>\n </div>\n );\n};\n\nexport default Notice;\n"],"names":["React","useEffect","Icon","cn","NoticeScripts","defaultTextColor","contentWrapperClasses","ContentWrapper","buttonLink","textColor","children","a","href","className","div","Notice","buttonLabel","bodyText","title","config","closeBtn","bgColor","bannerContainer","document","querySelector","cookieId","noticeId","options","collapse","data-id","style","maxHeight","overflow","strong","span","button","type","name","size","color"],"mappings":"AAAA,OAAOA,OAAoBC,SAAS,KAAQ,OAAQ,AAGpD,QAAOC,SAAU,QAAS,AAC1B,QAAOC,OAAQ,eAAgB,AAC/B,QAAOC,kBAAmB,uBAAwB,CAkClD,MAAMC,iBAAmB,0CAEzB,MAAMC,sBAAwB,qCAE9B,MAAMC,eAAiB,CAAC,CACtBC,UAAU,CACVC,UAAYJ,gBAAgB,CAC5BK,QAAQ,CACY,GACpBF,WACE,oBAACG,KAAEC,KAAMJ,WAAYK,UAAWV,GAAGG,sBAAuBG,YACvDC,UAGH,oBAACI,OAAID,UAAWV,GAAGG,sBAAuBG,YAAaC,UAG3D,MAAMK,OAAS,CAAC,CACdP,UAAU,CACVQ,WAAW,CACXC,QAAQ,CACRC,KAAK,CACLC,MAAM,CACNC,QAAQ,CACRC,QAAU,mCAAmC,CAC7CZ,UAAYJ,gBAAgB,CAChB,IACZJ,UAAU,KACRG,cAAc,CACZkB,gBAAiBC,SAASC,aAAa,CAAC,yBACxCC,SAAUN,QAAQM,SAClBC,SAAUP,QAAQO,SAClBC,QAAS,CACPC,SAAUT,QAAQQ,SAASC,UAAY,KACzC,CACF,EACF,EAAG,EAAE,EAEL,OACE,oBAACd,OACCD,UAAWV,GAAG,kBAAmBkB,QAASZ,WAC1CoB,UAAQ,YACRC,MAAO,CAAEC,UAAW,EAAGC,SAAU,QAAS,GAE1C,oBAAClB,OAAID,UAAU,6DACb,oBAACN,gBAAeC,WAAYA,YAAc,KACxC,oBAACyB,UAAOpB,UAAU,oCAAoCK,OACtD,oBAACgB,QAAKrB,UAAU,QAAQI,UACvBD,aACC,oBAACkB,QAAKrB,UAAU,gGACbG,cAKNI,UACC,oBAACe,UACCC,KAAK,SACLvB,UAAU,uDAEV,oBAACX,MACCmC,KAAK,0BACLC,KAAK,UACLC,MAAO9B,cAOrB,CAEA,gBAAeM,MAAO"}
1
+ {"version":3,"sources":["../../src/core/Notice.tsx"],"sourcesContent":["import React, { ReactNode, useEffect, useRef } from \"react\";\nimport DOMPurify from \"dompurify\";\n\nimport { ColorClass, ColorThemeSet } from \"./styles/colors/types\";\nimport Icon from \"./Icon\";\nimport cn from \"./utils/cn.js\";\nimport NoticeScripts from \"./Notice/component.js\";\nimport useRailsUjsLinks from \"./hooks/use-rails-ujs-hooks\";\n\ntype ContentWrapperProps = {\n buttonLink: string;\n children: ReactNode;\n textColor?: ColorClass | ColorThemeSet;\n};\n\n// TODO(jamiehenson):\n// This type is a bit messed up currently due to the NoticeScripts import being interpreted as NoticeProps.\n// Plan is to TS-ify the JS assets too, so this can be rectified then. The NoticeScripts-oriented props are\n// the ones after the line break.\nexport type NoticeProps = {\n buttonLink?: string;\n buttonLabel?: string;\n bodyText?: string;\n title?: string;\n closeBtn?: boolean;\n config?: {\n options: {\n collapse: boolean;\n };\n noticeId: string | number;\n cookieId: string;\n };\n bgColor?: string;\n textColor?: ColorClass | ColorThemeSet;\n\n bannerContainer?: Element | null;\n cookieId?: string;\n noticeId?: string;\n options?: { collapse: boolean };\n};\n\nconst defaultTextColor = \"text-neutral-1300 dark:text-neutral-000\";\n\nconst contentWrapperClasses = \"w-full pr-8 ui-text-p4 self-center\";\n\nconst ContentWrapper = ({\n buttonLink,\n textColor = defaultTextColor,\n children,\n}: ContentWrapperProps) =>\n buttonLink ? (\n <a href={buttonLink} className={cn(contentWrapperClasses, textColor)}>\n {children}\n </a>\n ) : (\n <div className={cn(contentWrapperClasses, textColor)}>{children}</div>\n );\n\nconst Notice = ({\n buttonLink,\n buttonLabel,\n bodyText,\n title,\n config,\n closeBtn,\n bgColor = \"bg-orange-100 dark:bg-orange-1100\",\n textColor = defaultTextColor,\n}: NoticeProps) => {\n const contentRef = useRef<HTMLSpanElement>(null);\n useRailsUjsLinks(contentRef);\n\n useEffect(() => {\n NoticeScripts({\n bannerContainer: document.querySelector('[data-id=\"ui-notice\"]'),\n cookieId: config?.cookieId,\n noticeId: config?.noticeId,\n options: {\n collapse: config?.options?.collapse || false,\n },\n });\n }, [config?.cookieId, config?.noticeId, config?.options?.collapse]);\n\n const safeContent = DOMPurify.sanitize(bodyText ?? \"\", {\n ALLOWED_TAGS: [\"a\"],\n ALLOWED_ATTR: [\"href\", \"data-method\"],\n ALLOWED_URI_REGEXP: /^\\/[^/]/,\n });\n\n return (\n <div\n className={cn(\"ui-announcement\", bgColor, textColor)}\n data-id=\"ui-notice\"\n style={{ maxHeight: 0, overflow: \"hidden\" }}\n >\n <div className=\"ui-grid-px py-16 max-w-screen-xl mx-auto flex items-start\">\n <ContentWrapper buttonLink={buttonLink ?? \"#\"}>\n <strong className=\"font-bold whitespace-nowrap pr-4\">{title}</strong>\n <span\n ref={contentRef}\n className=\"pr-4\"\n dangerouslySetInnerHTML={{\n __html: safeContent,\n }}\n ></span>\n {buttonLabel && (\n <span className=\"cursor-pointer whitespace-nowrap text-gui-blue-default-light dark:text-gui-blue-default-dark\">\n {buttonLabel}\n </span>\n )}\n </ContentWrapper>\n\n {closeBtn && (\n <button\n type=\"button\"\n className=\"ml-auto h-20 w-20 border-none bg-none self-baseline\"\n >\n <Icon\n name=\"icon-gui-x-mark-outline\"\n size=\"1.25rem\"\n color={textColor}\n />\n </button>\n )}\n </div>\n </div>\n );\n};\n\nexport default Notice;\n"],"names":["React","useEffect","useRef","DOMPurify","Icon","cn","NoticeScripts","useRailsUjsLinks","defaultTextColor","contentWrapperClasses","ContentWrapper","buttonLink","textColor","children","a","href","className","div","Notice","buttonLabel","bodyText","title","config","closeBtn","bgColor","contentRef","bannerContainer","document","querySelector","cookieId","noticeId","options","collapse","safeContent","sanitize","ALLOWED_TAGS","ALLOWED_ATTR","ALLOWED_URI_REGEXP","data-id","style","maxHeight","overflow","strong","span","ref","dangerouslySetInnerHTML","__html","button","type","name","size","color"],"mappings":"AAAA,OAAOA,OAAoBC,SAAS,CAAEC,MAAM,KAAQ,OAAQ,AAC5D,QAAOC,cAAe,WAAY,AAGlC,QAAOC,SAAU,QAAS,AAC1B,QAAOC,OAAQ,eAAgB,AAC/B,QAAOC,kBAAmB,uBAAwB,AAClD,QAAOC,qBAAsB,6BAA8B,CAkC3D,MAAMC,iBAAmB,0CAEzB,MAAMC,sBAAwB,qCAE9B,MAAMC,eAAiB,CAAC,CACtBC,UAAU,CACVC,UAAYJ,gBAAgB,CAC5BK,QAAQ,CACY,GACpBF,WACE,oBAACG,KAAEC,KAAMJ,WAAYK,UAAWX,GAAGI,sBAAuBG,YACvDC,UAGH,oBAACI,OAAID,UAAWX,GAAGI,sBAAuBG,YAAaC,UAG3D,MAAMK,OAAS,CAAC,CACdP,UAAU,CACVQ,WAAW,CACXC,QAAQ,CACRC,KAAK,CACLC,MAAM,CACNC,QAAQ,CACRC,QAAU,mCAAmC,CAC7CZ,UAAYJ,gBAAgB,CAChB,IACZ,MAAMiB,WAAavB,OAAwB,MAC3CK,iBAAiBkB,YAEjBxB,UAAU,KACRK,cAAc,CACZoB,gBAAiBC,SAASC,aAAa,CAAC,yBACxCC,SAAUP,QAAQO,SAClBC,SAAUR,QAAQQ,SAClBC,QAAS,CACPC,SAAUV,QAAQS,SAASC,UAAY,KACzC,CACF,EACF,EAAG,CAACV,QAAQO,SAAUP,QAAQQ,SAAUR,QAAQS,SAASC,SAAS,EAElE,MAAMC,YAAc9B,UAAU+B,QAAQ,CAACd,UAAY,GAAI,CACrDe,aAAc,CAAC,IAAI,CACnBC,aAAc,CAAC,OAAQ,cAAc,CACrCC,mBAAoB,SACtB,GAEA,OACE,oBAACpB,OACCD,UAAWX,GAAG,kBAAmBmB,QAASZ,WAC1C0B,UAAQ,YACRC,MAAO,CAAEC,UAAW,EAAGC,SAAU,QAAS,GAE1C,oBAACxB,OAAID,UAAU,6DACb,oBAACN,gBAAeC,WAAYA,YAAc,KACxC,oBAAC+B,UAAO1B,UAAU,oCAAoCK,OACtD,oBAACsB,QACCC,IAAKnB,WACLT,UAAU,OACV6B,wBAAyB,CACvBC,OAAQb,WACV,IAEDd,aACC,oBAACwB,QAAK3B,UAAU,gGACbG,cAKNI,UACC,oBAACwB,UACCC,KAAK,SACLhC,UAAU,uDAEV,oBAACZ,MACC6C,KAAK,0BACLC,KAAK,UACLC,MAAOvC,cAOrB,CAEA,gBAAeM,MAAO"}
@@ -0,0 +1,2 @@
1
+ import{useEffect}from"react";const useRailsUjsLinks=containerRef=>{useEffect(()=>{const container=containerRef.current;if(!container)return;const handleClick=event=>{if(!(event.target instanceof HTMLElement)){return}const target=event.target;const link=target.closest("a[data-method]");if(!link)return;if(!container.contains(link))return;event.preventDefault();const method=link.dataset.method?.toLowerCase()??"get";const href=link.getAttribute("href");if(!href){console.warn("Rails UJS link has no href attribute");return}if(method!=="post"&&method!=="delete")return;const csrfParam=document.querySelector('meta[name="csrf-param"]')?.content;const csrfToken=document.querySelector('meta[name="csrf-token"]')?.content;const form=document.createElement("form");form.method="POST";form.action=href;form.style.display="none";if(csrfParam&&csrfToken){const csrfInput=document.createElement("input");csrfInput.type="hidden";csrfInput.name=csrfParam;csrfInput.value=csrfToken;form.appendChild(csrfInput)}else{console.warn("No CSRF token found in document")}if(method!=="post"){const methodInput=document.createElement("input");methodInput.type="hidden";methodInput.name="_method";methodInput.value=method;form.appendChild(methodInput)}document.body.appendChild(form);form.submit()};container.addEventListener("click",handleClick);return()=>container.removeEventListener("click",handleClick)},[containerRef])};export default useRailsUjsLinks;
2
+ //# sourceMappingURL=use-rails-ujs-hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/core/hooks/use-rails-ujs-hooks.ts"],"sourcesContent":["import { useEffect, RefObject } from \"react\";\n\ntype HttpMethod = \"get\" | \"post\" | \"put\" | \"patch\" | \"delete\";\n\ninterface RailsUjsLink extends HTMLAnchorElement {\n dataset: {\n method?: string;\n confirm?: string;\n remote?: string;\n };\n}\n\ninterface CsrfMetaTag extends HTMLMetaElement {\n content: string;\n}\n\nconst useRailsUjsLinks = (containerRef: RefObject<HTMLElement>): void => {\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n const handleClick = (event: MouseEvent): void => {\n if (!(event.target instanceof HTMLElement)) {\n return;\n }\n\n const target = event.target;\n const link = target.closest<RailsUjsLink>(\"a[data-method]\");\n if (!link) return;\n\n // Check if the clicked link is within this component's container\n if (!container.contains(link)) return;\n\n event.preventDefault();\n\n const method = (link.dataset.method?.toLowerCase() ??\n \"get\") as HttpMethod;\n const href = link.getAttribute(\"href\");\n\n if (!href) {\n console.warn(\"Rails UJS link has no href attribute\");\n return;\n }\n\n // Only handle POST requests for now, expand for other methods if needed\n if (method !== \"post\" && method !== \"delete\") return;\n\n const csrfParam = document.querySelector<CsrfMetaTag>(\n 'meta[name=\"csrf-param\"]',\n )?.content;\n\n const csrfToken = document.querySelector<CsrfMetaTag>(\n 'meta[name=\"csrf-token\"]',\n )?.content;\n\n // Create and submit a hidden form\n const form = document.createElement(\"form\");\n form.method = \"POST\";\n form.action = href;\n form.style.display = \"none\";\n\n // Add CSRF token if present\n if (csrfParam && csrfToken) {\n const csrfInput = document.createElement(\"input\");\n csrfInput.type = \"hidden\";\n csrfInput.name = csrfParam;\n csrfInput.value = csrfToken;\n form.appendChild(csrfInput);\n } else {\n console.warn(\"No CSRF token found in document\");\n }\n\n // Add method override for non-POST methods\n if (method !== \"post\") {\n const methodInput = document.createElement(\"input\");\n methodInput.type = \"hidden\";\n methodInput.name = \"_method\";\n methodInput.value = method;\n form.appendChild(methodInput);\n }\n\n document.body.appendChild(form);\n form.submit();\n };\n\n container.addEventListener(\"click\", handleClick);\n return () => container.removeEventListener(\"click\", handleClick);\n }, [containerRef]);\n};\n\nexport default useRailsUjsLinks;\n"],"names":["useEffect","useRailsUjsLinks","containerRef","container","current","handleClick","event","target","HTMLElement","link","closest","contains","preventDefault","method","dataset","toLowerCase","href","getAttribute","console","warn","csrfParam","document","querySelector","content","csrfToken","form","createElement","action","style","display","csrfInput","type","name","value","appendChild","methodInput","body","submit","addEventListener","removeEventListener"],"mappings":"AAAA,OAASA,SAAS,KAAmB,OAAQ,CAgB7C,MAAMC,iBAAmB,AAACC,eACxBF,UAAU,KACR,MAAMG,UAAYD,aAAaE,OAAO,CACtC,GAAI,CAACD,UAAW,OAEhB,MAAME,YAAc,AAACC,QACnB,GAAI,CAAEA,CAAAA,MAAMC,MAAM,YAAYC,WAAU,EAAI,CAC1C,MACF,CAEA,MAAMD,OAASD,MAAMC,MAAM,CAC3B,MAAME,KAAOF,OAAOG,OAAO,CAAe,kBAC1C,GAAI,CAACD,KAAM,OAGX,GAAI,CAACN,UAAUQ,QAAQ,CAACF,MAAO,OAE/BH,MAAMM,cAAc,GAEpB,MAAMC,OAAUJ,KAAKK,OAAO,CAACD,MAAM,EAAEE,eACnC,MACF,MAAMC,KAAOP,KAAKQ,YAAY,CAAC,QAE/B,GAAI,CAACD,KAAM,CACTE,QAAQC,IAAI,CAAC,wCACb,MACF,CAGA,GAAIN,SAAW,QAAUA,SAAW,SAAU,OAE9C,MAAMO,UAAYC,SAASC,aAAa,CACtC,4BACCC,QAEH,MAAMC,UAAYH,SAASC,aAAa,CACtC,4BACCC,QAGH,MAAME,KAAOJ,SAASK,aAAa,CAAC,OACpCD,CAAAA,KAAKZ,MAAM,CAAG,MACdY,CAAAA,KAAKE,MAAM,CAAGX,IACdS,CAAAA,KAAKG,KAAK,CAACC,OAAO,CAAG,OAGrB,GAAIT,WAAaI,UAAW,CAC1B,MAAMM,UAAYT,SAASK,aAAa,CAAC,QACzCI,CAAAA,UAAUC,IAAI,CAAG,QACjBD,CAAAA,UAAUE,IAAI,CAAGZ,SACjBU,CAAAA,UAAUG,KAAK,CAAGT,UAClBC,KAAKS,WAAW,CAACJ,UACnB,KAAO,CACLZ,QAAQC,IAAI,CAAC,kCACf,CAGA,GAAIN,SAAW,OAAQ,CACrB,MAAMsB,YAAcd,SAASK,aAAa,CAAC,QAC3CS,CAAAA,YAAYJ,IAAI,CAAG,QACnBI,CAAAA,YAAYH,IAAI,CAAG,SACnBG,CAAAA,YAAYF,KAAK,CAAGpB,OACpBY,KAAKS,WAAW,CAACC,YACnB,CAEAd,SAASe,IAAI,CAACF,WAAW,CAACT,MAC1BA,KAAKY,MAAM,EACb,EAEAlC,UAAUmC,gBAAgB,CAAC,QAASjC,aACpC,MAAO,IAAMF,UAAUoC,mBAAmB,CAAC,QAASlC,YACtD,EAAG,CAACH,aAAa,CACnB,CAEA,gBAAeD,gBAAiB"}
@@ -1,5 +1,5 @@
1
1
  <svg width="50" height="48" viewBox="0 0 50 48" fill="none" xmlns="http://www.w3.org/2000/svg">
2
- <rect x="1" y="10" width="48" height="28" rx="14" stroke="#C6CED9" stroke-width="1.5"/>
3
- <path d="M37 18V29H34.848V19.939H34.7784L32 21.5825V19.7563L34.9524 18H37Z" fill="#C6CED9"/>
4
- <path d="M11.6801 17.7348C13.5995 15.7551 16.7207 15.7551 18.6401 17.7348L18.69 17.7862L18.7398 17.7348C20.6592 15.7551 23.7805 15.7551 25.6999 17.7348C27.6066 19.7016 27.6066 22.8803 25.6999 24.8471L19.6164 31.1219C19.1094 31.6448 18.2705 31.6448 17.7636 31.1219L11.6801 24.8471C9.77331 22.8803 9.77331 19.7016 11.6801 17.7348Z" fill="#FF5416"/>
2
+ <rect x="1" y="10" width="48" height="28" rx="14" stroke="#C6CED9" stroke-width="1.5"/>
3
+ <path d="M37 18V29H34.848V19.939H34.7784L32 21.5825V19.7563L34.9524 18H37Z" fill="#C6CED9"/>
4
+ <path d="M11.6801 17.7348C13.5995 15.7551 16.7207 15.7551 18.6401 17.7348L18.69 17.7862L18.7398 17.7348C20.6592 15.7551 23.7805 15.7551 25.6999 17.7348C27.6066 19.7016 27.6066 22.8803 25.6999 24.8471L19.6164 31.1219C19.1094 31.6448 18.2705 31.6448 17.7636 31.1219L11.6801 24.8471C9.77331 22.8803 9.77331 19.7016 11.6801 17.7348Z" fill="#FF5416"/>
5
5
  </svg>
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/remote-blogs-posts.js"],"sourcesContent":["/* global __ENABLE_FETCH_WITH_CREDENTIALS__ */\n\nimport { isJsonResponse } from \"./remote-data-util\";\n\nconst fetchBlogPosts = async (store, blogUrl) => {\n try {\n if (!blogUrl) {\n console.log(\n `Skipping fetching blog posts, invalid blogUrl: \"${blogUrl}\"`,\n );\n return;\n }\n\n const options = {\n headers: {\n accept: \"application/json\",\n },\n cache: \"no-cache\",\n };\n\n if (__ENABLE_FETCH_WITH_CREDENTIALS__) {\n options.credentials = \"include\";\n }\n\n const res = await fetch(blogUrl, options);\n\n if (isJsonResponse(res.headers.get(\"content-type\"))) {\n const payload = await res.json();\n store.dispatch({ type: \"blog/loaded\", payload });\n } else {\n throw new Error(\"Blog posts url is not serving json\");\n }\n } catch (e) {\n console.warn(\"Could not fetch blog posts due to error:\", e);\n }\n};\n\nconst initialState = { recent: null };\n\nconst REDUCER_KEY = \"blogPosts\";\n\nconst reducerBlogPosts = {\n [REDUCER_KEY]: (state = initialState, action) => {\n switch (action.type) {\n case \"blog/loaded\":\n return { ...state, recent: action.payload };\n default:\n return state;\n }\n },\n};\n\nconst selectRecentBlogPosts = (store) => store.getState()[REDUCER_KEY]?.recent;\n\nexport { fetchBlogPosts, reducerBlogPosts, selectRecentBlogPosts };\n"],"names":["isJsonResponse","fetchBlogPosts","store","blogUrl","console","log","options","headers","accept","cache","credentials","res","fetch","get","payload","json","dispatch","type","Error","e","warn","initialState","recent","REDUCER_KEY","reducerBlogPosts","state","action","selectRecentBlogPosts","getState"],"mappings":"AAEA,OAASA,cAAc,KAAQ,oBAAqB,CAEpD,MAAMC,eAAiB,MAAOC,MAAOC,WACnC,GAAI,CACF,GAAI,CAACA,QAAS,CACZC,QAAQC,GAAG,CACT,CAAC,gDAAgD,EAAEF,QAAQ,CAAC,CAAC,EAE/D,MACF,CAEA,MAAMG,QAAU,CACdC,QAAS,CACPC,OAAQ,kBACV,EACAC,MAAO,UACT,EAEA,GAWJ,MAX2C,CACrCH,QAAQI,WAAW,CAAG,SACxB,CAEA,MAAMC,IAAM,MAAMC,MAAMT,QAASG,SAEjC,GAAIN,eAAeW,IAAIJ,OAAO,CAACM,GAAG,CAAC,iBAAkB,CACnD,MAAMC,QAAU,MAAMH,IAAII,IAAI,GAC9Bb,MAAMc,QAAQ,CAAC,CAAEC,KAAM,cAAeH,OAAQ,EAChD,KAAO,CACL,MAAM,IAAII,MAAM,qCAClB,CACF,CAAE,MAAOC,EAAG,CACVf,QAAQgB,IAAI,CAAC,2CAA4CD,EAC3D,CACF,EAEA,MAAME,aAAe,CAAEC,OAAQ,IAAK,EAEpC,MAAMC,YAAc,YAEpB,MAAMC,iBAAmB,CACvB,CAACD,YAAY,CAAE,CAACE,MAAQJ,YAAY,CAAEK,UACpC,OAAQA,OAAOT,IAAI,EACjB,IAAK,cACH,MAAO,CAAE,GAAGQ,KAAK,CAAEH,OAAQI,OAAOZ,OAAO,AAAC,CAC5C,SACE,OAAOW,KACX,CACF,CACF,EAEA,MAAME,sBAAwB,AAACzB,OAAUA,MAAM0B,QAAQ,EAAE,CAACL,YAAY,EAAED,MAExE,QAASrB,cAAc,CAAEuB,gBAAgB,CAAEG,qBAAqB,CAAG"}
1
+ {"version":3,"sources":["../../src/core/remote-blogs-posts.js"],"sourcesContent":["/* global __ENABLE_FETCH_WITH_CREDENTIALS__ */\n\nimport { isJsonResponse } from \"./remote-data-util\";\n\nconst fetchBlogPosts = async (store, blogUrl) => {\n try {\n if (!blogUrl) {\n console.log(\n `Skipping fetching blog posts, invalid blogUrl: \"${blogUrl}\"`,\n );\n return;\n }\n\n const options = {\n headers: {\n accept: \"application/json\",\n },\n cache: \"no-cache\",\n };\n\n if (__ENABLE_FETCH_WITH_CREDENTIALS__) {\n options.credentials = \"include\";\n }\n\n const res = await fetch(blogUrl, options);\n\n if (isJsonResponse(res.headers.get(\"content-type\"))) {\n const payload = await res.json();\n store.dispatch({ type: \"blog/loaded\", payload });\n } else {\n throw new Error(\"Blog posts url is not serving json\");\n }\n } catch (e) {\n console.warn(\"Could not fetch blog posts due to error:\", e);\n }\n};\n\nconst initialState = { recent: null };\n\nconst REDUCER_KEY = \"blogPosts\";\n\nconst reducerBlogPosts = {\n [REDUCER_KEY]: (state = initialState, action) => {\n switch (action.type) {\n case \"blog/loaded\":\n return { ...state, recent: action.payload };\n default:\n return state;\n }\n },\n};\n\nconst selectRecentBlogPosts = (store) => store.getState()[REDUCER_KEY]?.recent;\n\nexport { fetchBlogPosts, reducerBlogPosts, selectRecentBlogPosts };\n"],"names":["isJsonResponse","fetchBlogPosts","store","blogUrl","console","log","options","headers","accept","cache","credentials","res","fetch","get","payload","json","dispatch","type","Error","e","warn","initialState","recent","REDUCER_KEY","reducerBlogPosts","state","action","selectRecentBlogPosts","getState"],"mappings":"AAEA,OAASA,cAAc,KAAQ,oBAAqB,CAEpD,MAAMC,eAAiB,MAAOC,MAAOC,WACnC,GAAI,CACF,GAAI,CAACA,QAAS,CACZC,QAAQC,GAAG,CACT,CAAC,gDAAgD,EAAEF,QAAQ,CAAC,CAAC,EAE/D,MACF,CAEA,MAAMG,QAAU,CACdC,QAAS,CACPC,OAAQ,kBACV,EACAC,MAAO,UACT,EAEA,SAAuC,CACrCH,QAAQI,WAAW,CAAG,SACxB,CAEA,MAAMC,IAAM,MAAMC,MAAMT,QAASG,SAEjC,GAAIN,eAAeW,IAAIJ,OAAO,CAACM,GAAG,CAAC,iBAAkB,CACnD,MAAMC,QAAU,MAAMH,IAAII,IAAI,GAC9Bb,MAAMc,QAAQ,CAAC,CAAEC,KAAM,cAAeH,OAAQ,EAChD,KAAO,CACL,MAAM,IAAII,MAAM,qCAClB,CACF,CAAE,MAAOC,EAAG,CACVf,QAAQgB,IAAI,CAAC,2CAA4CD,EAC3D,CACF,EAEA,MAAME,aAAe,CAAEC,OAAQ,IAAK,EAEpC,MAAMC,YAAc,YAEpB,MAAMC,iBAAmB,CACvB,CAACD,YAAY,CAAE,CAACE,MAAQJ,YAAY,CAAEK,UACpC,OAAQA,OAAOT,IAAI,EACjB,IAAK,cACH,MAAO,CAAE,GAAGQ,KAAK,CAAEH,OAAQI,OAAOZ,OAAO,AAAC,CAC5C,SACE,OAAOW,KACX,CACF,CACF,EAEA,MAAME,sBAAwB,AAACzB,OAAUA,MAAM0B,QAAQ,EAAE,CAACL,YAAY,EAAED,MAExE,QAASrB,cAAc,CAAEuB,gBAAgB,CAAEG,qBAAqB,CAAG"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/remote-session-data.js"],"sourcesContent":["/* global __ENABLE_FETCH_WITH_CREDENTIALS__ */\n\n// Fetches current users session data\n// Assumes an authenticated session, so will only work when used on ably.com/ably.io\n\nimport { isJsonResponse } from \"./remote-data-util\";\n\nconst NOT_FOUND_ERROR_CODE = \"not-found\";\n\nconst fetchSessionData = async (store, sessionUrl) => {\n const sessionLoaded = (payload = {}) =>\n store.dispatch({ type: \"session/loaded\", payload });\n\n try {\n if (!sessionUrl) {\n console.log(\n `Skipping fetching session, invalid sessionUrl: \"${sessionUrl}\"`,\n );\n sessionLoaded();\n return;\n }\n\n const options = {\n headers: {\n accept: \"application/json\",\n },\n cache: \"no-cache\",\n };\n\n if (__ENABLE_FETCH_WITH_CREDENTIALS__) {\n options.credentials = \"include\";\n }\n\n const res = await fetch(sessionUrl, options);\n const jsonResponse = isJsonResponse(res.headers.get(\"content-type\"));\n\n if (!jsonResponse) {\n throw new Error(\"Session endpoint is not serving json\");\n }\n\n const payload = await res.json();\n\n if (payload.error === NOT_FOUND_ERROR_CODE) {\n sessionLoaded();\n } else {\n sessionLoaded(payload);\n }\n } catch (e) {\n sessionLoaded();\n console.warn(\"Could not fetch session data due to error:\", e);\n }\n};\n\nconst initialState = { data: null };\n\nconst REDUCER_KEY = \"session\";\n\nconst reducerSessionData = {\n [REDUCER_KEY]: (state = initialState, action) => {\n switch (action.type) {\n case \"session/loaded\":\n return { ...state, data: action.payload };\n default:\n return state;\n }\n },\n};\n\nconst selectSessionData = (store) => store.getState()[REDUCER_KEY]?.data;\n\nexport { fetchSessionData, reducerSessionData, selectSessionData };\n"],"names":["isJsonResponse","NOT_FOUND_ERROR_CODE","fetchSessionData","store","sessionUrl","sessionLoaded","payload","dispatch","type","console","log","options","headers","accept","cache","credentials","res","fetch","jsonResponse","get","Error","json","error","e","warn","initialState","data","REDUCER_KEY","reducerSessionData","state","action","selectSessionData","getState"],"mappings":"AAKA,OAASA,cAAc,KAAQ,oBAAqB,CAEpD,MAAMC,qBAAuB,YAE7B,MAAMC,iBAAmB,MAAOC,MAAOC,cACrC,MAAMC,cAAgB,CAACC,QAAU,CAAC,CAAC,GACjCH,MAAMI,QAAQ,CAAC,CAAEC,KAAM,iBAAkBF,OAAQ,GAEnD,GAAI,CACF,GAAI,CAACF,WAAY,CACfK,QAAQC,GAAG,CACT,CAAC,gDAAgD,EAAEN,WAAW,CAAC,CAAC,EAElEC,gBACA,MACF,CAEA,MAAMM,QAAU,CACdC,QAAS,CACPC,OAAQ,kBACV,EACAC,MAAO,UACT,EAEA,GACkB,MADqB,CACrCH,QAAQI,WAAW,CAAG,SACxB,CAEA,MAAMC,IAAM,MAAMC,MAAMb,WAAYO,SACpC,MAAMO,aAAelB,eAAegB,IAAIJ,OAAO,CAACO,GAAG,CAAC,iBAEpD,GAAI,CAACD,aAAc,CACjB,MAAM,IAAIE,MAAM,uCAClB,CAEA,MAAMd,QAAU,MAAMU,IAAIK,IAAI,GAE9B,GAAIf,QAAQgB,KAAK,GAAKrB,qBAAsB,CAC1CI,eACF,KAAO,CACLA,cAAcC,QAChB,CACF,CAAE,MAAOiB,EAAG,CACVlB,gBACAI,QAAQe,IAAI,CAAC,6CAA8CD,EAC7D,CACF,EAEA,MAAME,aAAe,CAAEC,KAAM,IAAK,EAElC,MAAMC,YAAc,UAEpB,MAAMC,mBAAqB,CACzB,CAACD,YAAY,CAAE,CAACE,MAAQJ,YAAY,CAAEK,UACpC,OAAQA,OAAOtB,IAAI,EACjB,IAAK,iBACH,MAAO,CAAE,GAAGqB,KAAK,CAAEH,KAAMI,OAAOxB,OAAO,AAAC,CAC1C,SACE,OAAOuB,KACX,CACF,CACF,EAEA,MAAME,kBAAoB,AAAC5B,OAAUA,MAAM6B,QAAQ,EAAE,CAACL,YAAY,EAAED,IAEpE,QAASxB,gBAAgB,CAAE0B,kBAAkB,CAAEG,iBAAiB,CAAG"}
1
+ {"version":3,"sources":["../../src/core/remote-session-data.js"],"sourcesContent":["/* global __ENABLE_FETCH_WITH_CREDENTIALS__ */\n\n// Fetches current users session data\n// Assumes an authenticated session, so will only work when used on ably.com/ably.io\n\nimport { isJsonResponse } from \"./remote-data-util\";\n\nconst NOT_FOUND_ERROR_CODE = \"not-found\";\n\nconst fetchSessionData = async (store, sessionUrl) => {\n const sessionLoaded = (payload = {}) =>\n store.dispatch({ type: \"session/loaded\", payload });\n\n try {\n if (!sessionUrl) {\n console.log(\n `Skipping fetching session, invalid sessionUrl: \"${sessionUrl}\"`,\n );\n sessionLoaded();\n return;\n }\n\n const options = {\n headers: {\n accept: \"application/json\",\n },\n cache: \"no-cache\",\n };\n\n if (__ENABLE_FETCH_WITH_CREDENTIALS__) {\n options.credentials = \"include\";\n }\n\n const res = await fetch(sessionUrl, options);\n const jsonResponse = isJsonResponse(res.headers.get(\"content-type\"));\n\n if (!jsonResponse) {\n throw new Error(\"Session endpoint is not serving json\");\n }\n\n const payload = await res.json();\n\n if (payload.error === NOT_FOUND_ERROR_CODE) {\n sessionLoaded();\n } else {\n sessionLoaded(payload);\n }\n } catch (e) {\n sessionLoaded();\n console.warn(\"Could not fetch session data due to error:\", e);\n }\n};\n\nconst initialState = { data: null };\n\nconst REDUCER_KEY = \"session\";\n\nconst reducerSessionData = {\n [REDUCER_KEY]: (state = initialState, action) => {\n switch (action.type) {\n case \"session/loaded\":\n return { ...state, data: action.payload };\n default:\n return state;\n }\n },\n};\n\nconst selectSessionData = (store) => store.getState()[REDUCER_KEY]?.data;\n\nexport { fetchSessionData, reducerSessionData, selectSessionData };\n"],"names":["isJsonResponse","NOT_FOUND_ERROR_CODE","fetchSessionData","store","sessionUrl","sessionLoaded","payload","dispatch","type","console","log","options","headers","accept","cache","credentials","res","fetch","jsonResponse","get","Error","json","error","e","warn","initialState","data","REDUCER_KEY","reducerSessionData","state","action","selectSessionData","getState"],"mappings":"AAKA,OAASA,cAAc,KAAQ,oBAAqB,CAEpD,MAAMC,qBAAuB,YAE7B,MAAMC,iBAAmB,MAAOC,MAAOC,cACrC,MAAMC,cAAgB,CAACC,QAAU,CAAC,CAAC,GACjCH,MAAMI,QAAQ,CAAC,CAAEC,KAAM,iBAAkBF,OAAQ,GAEnD,GAAI,CACF,GAAI,CAACF,WAAY,CACfK,QAAQC,GAAG,CACT,CAAC,gDAAgD,EAAEN,WAAW,CAAC,CAAC,EAElEC,gBACA,MACF,CAEA,MAAMM,QAAU,CACdC,QAAS,CACPC,OAAQ,kBACV,EACAC,MAAO,UACT,EAEA,SAAuC,CACrCH,QAAQI,WAAW,CAAG,SACxB,CAEA,MAAMC,IAAM,MAAMC,MAAMb,WAAYO,SACpC,MAAMO,aAAelB,eAAegB,IAAIJ,OAAO,CAACO,GAAG,CAAC,iBAEpD,GAAI,CAACD,aAAc,CACjB,MAAM,IAAIE,MAAM,uCAClB,CAEA,MAAMd,QAAU,MAAMU,IAAIK,IAAI,GAE9B,GAAIf,QAAQgB,KAAK,GAAKrB,qBAAsB,CAC1CI,eACF,KAAO,CACLA,cAAcC,QAChB,CACF,CAAE,MAAOiB,EAAG,CACVlB,gBACAI,QAAQe,IAAI,CAAC,6CAA8CD,EAC7D,CACF,EAEA,MAAME,aAAe,CAAEC,KAAM,IAAK,EAElC,MAAMC,YAAc,UAEpB,MAAMC,mBAAqB,CACzB,CAACD,YAAY,CAAE,CAACE,MAAQJ,YAAY,CAAEK,UACpC,OAAQA,OAAOtB,IAAI,EACjB,IAAK,iBACH,MAAO,CAAE,GAAGqB,KAAK,CAAEH,KAAMI,OAAOxB,OAAO,AAAC,CAC1C,SACE,OAAOuB,KACX,CACF,CACF,EAEA,MAAME,kBAAoB,AAAC5B,OAAUA,MAAM6B,QAAQ,EAAE,CAACL,YAAY,EAAED,IAEpE,QAASxB,gBAAgB,CAAE0B,kBAAkB,CAAEG,iBAAiB,CAAG"}
package/index.d.ts CHANGED
@@ -441,7 +441,7 @@ type FlashProps = {
441
441
  };
442
442
  type FlashesProps = {
443
443
  flashes: {
444
- items: FlashProps[];
444
+ items: Pick<FlashProps, "type" | "content">[];
445
445
  };
446
446
  };
447
447
  type BackendFlashesProps = {
@@ -1326,6 +1326,13 @@ export function queryIdAll(val: any, root?: Document): NodeListOf<Element>;
1326
1326
  //# sourceMappingURL=dom-query.d.ts.map
1327
1327
  }
1328
1328
 
1329
+ declare module '@ably/ui/core/hooks/use-rails-ujs-hooks' {
1330
+ import { RefObject } from "react";
1331
+ const useRailsUjsLinks: (containerRef: RefObject<HTMLElement>) => void;
1332
+ export default useRailsUjsLinks;
1333
+ //# sourceMappingURL=use-rails-ujs-hooks.d.ts.map
1334
+ }
1335
+
1329
1336
  declare module '@ably/ui/core/remote-data-store' {
1330
1337
  export function attachStoreToWindow(store: any): void;
1331
1338
  export function getRemoteDataStore(): any;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ably/ui",
3
- "version": "16.1.2-dev.7eaf96b5",
3
+ "version": "16.1.2-dev.8dee7a5e",
4
4
  "description": "Home of the Ably design system library ([design.ably.com](https://design.ably.com)). It provides a showcase, development/test environment and a publishing pipeline for different distributables.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -20,10 +20,11 @@
20
20
  },
21
21
  "devDependencies": {
22
22
  "@storybook/addon-essentials": "^8.6.4",
23
+ "@storybook/addon-interactions": "^8.6.4",
23
24
  "@storybook/react-vite": "^8.6.4",
24
25
  "@storybook/test": "^8.6.4",
25
26
  "@storybook/test-runner": "^0.22.0",
26
- "@swc/cli": "^0.6.0",
27
+ "@swc/cli": "^0.7.3",
27
28
  "@swc/core": "^1.4.11",
28
29
  "@tailwindcss/container-queries": "^0.1.1",
29
30
  "@types/js-cookie": "^3.0.6",
@@ -68,9 +69,9 @@
68
69
  "build:sprites": "ts-node scripts/generate-sprites.ts",
69
70
  "build": "yarn build:prebuild && yarn build:sprites && yarn build:swc && yarn build:tsc && yarn build:cleanup",
70
71
  "watch": "yarn build:swc -w",
71
- "format:check": "prettier -c *.{js,ts} src/**/*.{js,ts,tsx}",
72
- "format:write": "prettier -w *.{js,ts} src/**/*.{js,ts,tsx}",
73
- "lint": "eslint *.{js,ts} src/**/*.{js,ts,tsx}",
72
+ "format:check": "prettier -c *.{js,ts} src/**/*.{js,ts,tsx,stories.tsx}",
73
+ "format:write": "prettier -w *.{js,ts} src/**/*.{js,ts,tsx,stories.tsx}",
74
+ "lint": "eslint *.{js,ts} src/**/*.{js,ts,tsx,stories.tsx}",
74
75
  "update:all": "./scripts/update-dependents.sh",
75
76
  "pre-release": "./scripts/pre-release.sh",
76
77
  "release": "./scripts/release.sh",