spry-apps-dropdown 1.0.0

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/README.md ADDED
@@ -0,0 +1,249 @@
1
+ # @spry/apps-dropdown
2
+
3
+ A React component for displaying Spry apps in a dropdown menu with dynamic API integration.
4
+
5
+ ## Features
6
+
7
+ - 🎨 Beautiful Material-UI design with smooth animations
8
+ - 🔄 Automatic data fetching from API
9
+ - 💾 Built-in caching and refetching
10
+ - âš¡ Loading and error states
11
+ - 📱 Responsive layout
12
+ - 🎯 TypeScript support
13
+ - 🔌 Easy integration
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ npm install @spry/apps-dropdown
19
+ ```
20
+
21
+ ### Peer Dependencies
22
+
23
+ Make sure you have these installed:
24
+
25
+ ```bash
26
+ npm install react react-dom @mui/material framer-motion @emotion/react @emotion/styled
27
+ ```
28
+
29
+ ## Usage
30
+
31
+ ### Basic Usage (Recommended)
32
+
33
+ Import `AppsDropdownConnected` for automatic API integration:
34
+
35
+ ```tsx
36
+ import { useState, useRef } from 'react'
37
+ import { IconButton } from '@mui/material'
38
+ import { Apps } from '@mui/icons-material'
39
+ import { AppsDropdownConnected } from '@spry/apps-dropdown'
40
+
41
+ function MyComponent() {
42
+ const [appsMenuOpen, setAppsMenuOpen] = useState(false)
43
+ const appsButtonRef = useRef<HTMLButtonElement>(null)
44
+
45
+ return (
46
+ <>
47
+ <IconButton
48
+ ref={appsButtonRef}
49
+ onClick={() => setAppsMenuOpen(!appsMenuOpen)}
50
+ >
51
+ <Apps />
52
+ </IconButton>
53
+
54
+ <AppsDropdownConnected
55
+ apiUrl="http://localhost:3002"
56
+ open={appsMenuOpen}
57
+ onClose={() => setAppsMenuOpen(false)}
58
+ buttonRef={appsButtonRef}
59
+ />
60
+ </>
61
+ )
62
+ }
63
+ ```
64
+
65
+ ### Advanced Usage
66
+
67
+ Use `AppsDropdown` directly with custom data source:
68
+
69
+ ```tsx
70
+ import { AppsDropdown, useAppsData } from '@spry/apps-dropdown'
71
+
72
+ function MyComponent() {
73
+ const [appsMenuOpen, setAppsMenuOpen] = useState(false)
74
+ const appsButtonRef = useRef<HTMLButtonElement>(null)
75
+
76
+ // Use the hook for more control
77
+ const { apps, isLoading, error, refetch } = useAppsData('http://localhost:3002', {
78
+ refetchInterval: 10 * 60 * 1000, // 10 minutes
79
+ cacheTime: 10 * 60 * 1000 // 10 minutes
80
+ })
81
+
82
+ return (
83
+ <>
84
+ <IconButton ref={appsButtonRef} onClick={() => setAppsMenuOpen(!appsMenuOpen)}>
85
+ <Apps />
86
+ </IconButton>
87
+
88
+ <AppsDropdown
89
+ apps={apps}
90
+ open={appsMenuOpen}
91
+ onClose={() => setAppsMenuOpen(false)}
92
+ buttonRef={appsButtonRef}
93
+ isLoading={isLoading}
94
+ error={error}
95
+ onRetry={refetch}
96
+ />
97
+ </>
98
+ )
99
+ }
100
+ ```
101
+
102
+ ## API Reference
103
+
104
+ ### `AppsDropdownConnected`
105
+
106
+ The main component with automatic API integration.
107
+
108
+ #### Props
109
+
110
+ | Prop | Type | Required | Default | Description |
111
+ |------|------|----------|---------|-------------|
112
+ | `apiUrl` | `string` | Yes | - | Base URL of the Spry Apps API |
113
+ | `open` | `boolean` | Yes | - | Whether the dropdown is open |
114
+ | `onClose` | `() => void` | Yes | - | Callback when dropdown closes |
115
+ | `buttonRef` | `React.RefObject<HTMLButtonElement>` | No | - | Ref for positioning |
116
+ | `refetchInterval` | `number` | No | `300000` (5 min) | Auto-refetch interval in ms |
117
+ | `cacheTime` | `number` | No | `300000` (5 min) | Cache duration in ms |
118
+
119
+ ### `AppsDropdown`
120
+
121
+ The presentational component for custom implementations.
122
+
123
+ #### Props
124
+
125
+ | Prop | Type | Required | Default | Description |
126
+ |------|------|----------|---------|-------------|
127
+ | `apps` | `App[]` | Yes | - | Array of apps to display |
128
+ | `open` | `boolean` | Yes | - | Whether the dropdown is open |
129
+ | `onClose` | `() => void` | Yes | - | Callback when dropdown closes |
130
+ | `buttonRef` | `React.RefObject<HTMLButtonElement>` | No | - | Ref for positioning |
131
+ | `isLoading` | `boolean` | No | `false` | Loading state |
132
+ | `error` | `string \| null` | No | `null` | Error message |
133
+ | `onRetry` | `() => void` | No | - | Retry callback |
134
+
135
+ ### `useAppsData`
136
+
137
+ Hook for fetching apps data.
138
+
139
+ #### Parameters
140
+
141
+ ```typescript
142
+ useAppsData(apiUrl: string, options?: {
143
+ refetchInterval?: number // Default: 300000 (5 minutes)
144
+ cacheTime?: number // Default: 300000 (5 minutes)
145
+ })
146
+ ```
147
+
148
+ #### Returns
149
+
150
+ ```typescript
151
+ {
152
+ apps: App[] // Array of apps
153
+ isLoading: boolean // Loading state
154
+ error: string | null // Error message if any
155
+ refetch: () => Promise<void> // Manual refetch function
156
+ }
157
+ ```
158
+
159
+ ### Types
160
+
161
+ ```typescript
162
+ interface App {
163
+ id: string
164
+ name: string
165
+ description: string
166
+ url: string
167
+ iconUrl: string
168
+ color: string
169
+ order: number
170
+ createdAt: string
171
+ updatedAt: string
172
+ }
173
+ ```
174
+
175
+ ## Backend API Requirements
176
+
177
+ The component expects the following API endpoint structure:
178
+
179
+ ### `GET /api/apps`
180
+
181
+ Returns:
182
+ ```json
183
+ {
184
+ "apps": [
185
+ {
186
+ "id": "abc123",
187
+ "name": "SpryBoard",
188
+ "description": "Collaborative whiteboard",
189
+ "url": "https://board.spry.com",
190
+ "iconUrl": "https://example.com/icon.png",
191
+ "color": "#4285f4",
192
+ "order": 1,
193
+ "createdAt": "2026-02-13T10:00:00.000Z",
194
+ "updatedAt": "2026-02-13T10:00:00.000Z"
195
+ }
196
+ ],
197
+ "lastUpdated": "2026-02-13T10:00:00.000Z"
198
+ }
199
+ ```
200
+
201
+ See [spry-apps-server](https://github.com/your-org/spry-apps-server) for the reference backend implementation.
202
+
203
+ ## Styling
204
+
205
+ The component uses Material-UI components. You can customize the appearance using the MUI theme:
206
+
207
+ ```tsx
208
+ import { ThemeProvider, createTheme } from '@mui/material/styles'
209
+
210
+ const theme = createTheme({
211
+ // Your custom theme
212
+ })
213
+
214
+ function App() {
215
+ return (
216
+ <ThemeProvider theme={theme}>
217
+ <AppsDropdownConnected {...props} />
218
+ </ThemeProvider>
219
+ )
220
+ }
221
+ ```
222
+
223
+ ## Caching
224
+
225
+ The component automatically caches apps data in `localStorage` to provide instant loading on subsequent visits. The cache respects the `cacheTime` option.
226
+
227
+ ## Error Handling
228
+
229
+ - Network errors are caught and displayed with a retry button
230
+ - Cached data is used as fallback when API is unavailable
231
+ - Loading spinner shown during initial fetch
232
+
233
+ ## Browser Support
234
+
235
+ - Modern browsers with ES2020 support
236
+ - Requires localStorage API
237
+
238
+ ## License
239
+
240
+ MIT
241
+
242
+ ## Contributing
243
+
244
+ Contributions are welcome! Please open an issue or submit a pull request.
245
+
246
+ ## Related
247
+
248
+ - [Spry Apps Server](https://github.com/your-org/spry-apps-server) - Backend API server
249
+ - [Spry Account](https://github.com/your-org/spry-account) - Reference implementation
@@ -0,0 +1,2 @@
1
+ import type { AppsDropdownProps } from './types';
2
+ export declare function AppsDropdown({ apps, open, onClose, buttonRef, isLoading, error, onRetry }: AppsDropdownProps): import("react/jsx-runtime").JSX.Element;
package/dist/index.cjs ADDED
@@ -0,0 +1,7 @@
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const x=require("react"),g=require("@mui/material"),W=require("framer-motion");var O={exports:{}},k={};var q;function ce(){if(q)return k;q=1;var c=Symbol.for("react.transitional.element"),E=Symbol.for("react.fragment");function f(l,u,i){var h=null;if(i!==void 0&&(h=""+i),u.key!==void 0&&(h=""+u.key),"key"in u){i={};for(var d in u)d!=="key"&&(i[d]=u[d])}else i=u;return u=i.ref,{$$typeof:c,type:l,key:h,ref:u!==void 0?u:null,props:i}}return k.Fragment=E,k.jsx=f,k.jsxs=f,k}var j={};var H;function ie(){return H||(H=1,process.env.NODE_ENV!=="production"&&(function(){function c(e){if(e==null)return null;if(typeof e=="function")return e.$$typeof===oe?null:e.displayName||e.name||null;if(typeof e=="string")return e;switch(e){case p:return"Fragment";case G:return"Profiler";case w:return"StrictMode";case ee:return"Suspense";case re:return"SuspenseList";case ne:return"Activity"}if(typeof e=="object")switch(typeof e.tag=="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),e.$$typeof){case o:return"Portal";case Q:return e.displayName||"Context";case Z:return(e._context.displayName||"Context")+".Consumer";case K:var r=e.render;return e=e.displayName,e||(e=r.displayName||r.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case te:return r=e.displayName||null,r!==null?r:c(e.type)||"Memo";case C:r=e._payload,e=e._init;try{return c(e(r))}catch{}}return null}function E(e){return""+e}function f(e){try{E(e);var r=!1}catch{r=!0}if(r){r=console;var n=r.error,a=typeof Symbol=="function"&&Symbol.toStringTag&&e[Symbol.toStringTag]||e.constructor.name||"Object";return n.call(r,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",a),E(e)}}function l(e){if(e===p)return"<>";if(typeof e=="object"&&e!==null&&e.$$typeof===C)return"<...>";try{var r=c(e);return r?"<"+r+">":"<...>"}catch{return"<...>"}}function u(){var e=P.A;return e===null?null:e.getOwner()}function i(){return Error("react-stack-top-frame")}function h(e){if(F.call(e,"key")){var r=Object.getOwnPropertyDescriptor(e,"key").get;if(r&&r.isReactWarning)return!1}return e.key!==void 0}function d(e,r){function n(){L||(L=!0,console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",r))}n.isReactWarning=!0,Object.defineProperty(e,"key",{get:n,configurable:!0})}function R(){var e=c(this.type);return $[e]||($[e]=!0,console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.")),e=this.props.ref,e!==void 0?e:null}function b(e,r,n,a,S,I){var s=n.ref;return e={$$typeof:y,type:e,key:r,props:n,_owner:a},(s!==void 0?s:null)!==null?Object.defineProperty(e,"ref",{enumerable:!1,get:R}):Object.defineProperty(e,"ref",{enumerable:!1,value:null}),e._store={},Object.defineProperty(e._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(e,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(e,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:S}),Object.defineProperty(e,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:I}),Object.freeze&&(Object.freeze(e.props),Object.freeze(e)),e}function v(e,r,n,a,S,I){var s=r.children;if(s!==void 0)if(a)if(ae(s)){for(a=0;a<s.length;a++)t(s[a]);Object.freeze&&Object.freeze(s)}else console.error("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");else t(s);if(F.call(r,"key")){s=c(e);var A=Object.keys(r).filter(function(se){return se!=="key"});a=0<A.length?"{key: someKey, "+A.join(": ..., ")+": ...}":"{key: someKey}",U[s+a]||(A=0<A.length?"{"+A.join(": ..., ")+": ...}":"{}",console.error(`A props object containing a "key" prop is being spread into JSX:
2
+ let props = %s;
3
+ <%s {...props} />
4
+ React keys must be passed directly to JSX without using spread:
5
+ let props = %s;
6
+ <%s key={someKey} {...props} />`,a,s,A,s),U[s+a]=!0)}if(s=null,n!==void 0&&(f(n),s=""+n),h(r)&&(f(r.key),s=""+r.key),"key"in r){n={};for(var D in r)D!=="key"&&(n[D]=r[D])}else n=r;return s&&d(n,typeof e=="function"?e.displayName||e.name||"Unknown":e),b(e,s,n,u(),S,I)}function t(e){_(e)?e._store&&(e._store.validated=1):typeof e=="object"&&e!==null&&e.$$typeof===C&&(e._payload.status==="fulfilled"?_(e._payload.value)&&e._payload.value._store&&(e._payload.value._store.validated=1):e._store&&(e._store.validated=1))}function _(e){return typeof e=="object"&&e!==null&&e.$$typeof===y}var T=x,y=Symbol.for("react.transitional.element"),o=Symbol.for("react.portal"),p=Symbol.for("react.fragment"),w=Symbol.for("react.strict_mode"),G=Symbol.for("react.profiler"),Z=Symbol.for("react.consumer"),Q=Symbol.for("react.context"),K=Symbol.for("react.forward_ref"),ee=Symbol.for("react.suspense"),re=Symbol.for("react.suspense_list"),te=Symbol.for("react.memo"),C=Symbol.for("react.lazy"),ne=Symbol.for("react.activity"),oe=Symbol.for("react.client.reference"),P=T.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,F=Object.prototype.hasOwnProperty,ae=Array.isArray,N=console.createTask?console.createTask:function(){return null};T={react_stack_bottom_frame:function(e){return e()}};var L,$={},M=T.react_stack_bottom_frame.bind(T,i)(),z=N(l(i)),U={};j.Fragment=p,j.jsx=function(e,r,n){var a=1e4>P.recentlyCreatedOwnerStacks++;return v(e,r,n,!1,a?Error("react-stack-top-frame"):M,a?N(l(e)):z)},j.jsxs=function(e,r,n){var a=1e4>P.recentlyCreatedOwnerStacks++;return v(e,r,n,!0,a?Error("react-stack-top-frame"):M,a?N(l(e)):z)}})()),j}var B;function le(){return B||(B=1,process.env.NODE_ENV==="production"?O.exports=ce():O.exports=ie()),O.exports}var m=le();function J({apps:c,open:E,onClose:f,buttonRef:l,isLoading:u=!1,error:i=null,onRetry:h}){const d=x.useRef(null),[R,b]=x.useState("64px");x.useLayoutEffect(()=>{if(E&&l?.current){const t=l.current.getBoundingClientRect();b(`${t.bottom+8}px`)}},[E,l]),x.useEffect(()=>{const t=_=>{d.current&&!d.current.contains(_.target)&&l?.current&&!l.current.contains(_.target)&&f()};return E&&document.addEventListener("mousedown",t),()=>{document.removeEventListener("mousedown",t)}},[E,f,l]);const v=t=>{window.open(t,"_blank"),f()};return m.jsx(W.AnimatePresence,{children:E&&m.jsx(W.motion.div,{ref:d,initial:{opacity:0,scaleX:.6,scaleY:.6,y:-8},animate:{opacity:1,scaleX:1,scaleY:1,y:0},exit:{opacity:0,scaleX:.6,scaleY:.6,y:-8},transition:{duration:.18,ease:"easeOut"},style:{position:"absolute",top:R,right:"16px",zIndex:1e3,transformOrigin:"top right"},children:m.jsxs(g.Box,{sx:{bgcolor:"#E8F0FE",borderRadius:"8px",boxShadow:"0 2px 8px rgba(0, 0, 0, 0.1)",p:2,width:"320px",minHeight:"100px"},onClick:t=>t.stopPropagation(),children:[u&&c.length===0&&m.jsx(g.Box,{sx:{display:"flex",justifyContent:"center",alignItems:"center",minHeight:"100px"},children:m.jsx(g.CircularProgress,{size:32})}),i&&c.length===0&&m.jsxs(g.Box,{sx:{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",minHeight:"100px",gap:1},children:[m.jsx(g.Typography,{sx:{fontSize:"0.875rem",color:"#ea4335",textAlign:"center"},children:"Failed to load apps"}),h&&m.jsx(g.Link,{component:"button",onClick:h,sx:{fontSize:"0.875rem",color:"#1a73e8",cursor:"pointer",textDecoration:"underline"},children:"Retry"})]}),c.length>0&&m.jsx(g.Box,{sx:{display:"grid",gridTemplateColumns:"repeat(3, 1fr)",gap:1},children:c.map(t=>m.jsxs(g.Link,{onClick:()=>v(t.url),sx:{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",minHeight:"100px",p:1.5,borderRadius:"12px",cursor:"pointer",textDecoration:"none",transition:"background-color 200ms","&:hover":{bgcolor:"#f1f3f4"}},title:t.description,children:[m.jsx(g.Box,{sx:{pb:1},children:t.iconUrl?m.jsx(g.Box,{component:"img",src:t.iconUrl,alt:t.name,sx:{width:"32px",height:"32px",objectFit:"contain"}}):m.jsx(g.Box,{sx:{width:"32px",height:"32px",borderRadius:"6px",bgcolor:t.color||"#4285f4",display:"flex",alignItems:"center",justifyContent:"center",fontSize:"1.5rem"},children:t.name.charAt(0)})}),m.jsx(g.Typography,{sx:{fontSize:"0.75rem",fontWeight:500,color:"#202124",textAlign:"center",lineHeight:1.2},children:t.name})]},t.id))})]})})})}const Y="spry_apps_cache",ue=300*1e3,fe=300*1e3;function V(c,E={}){const{refetchInterval:f=ue,cacheTime:l=fe}=E,[u,i]=x.useState([]),[h,d]=x.useState(!0),[R,b]=x.useState(null),v=x.useRef(null),t=x.useRef(null),_=x.useCallback(()=>{try{const o=localStorage.getItem(Y);if(!o)return null;const p=JSON.parse(o);return Date.now()-p.timestamp<l?p.apps:(localStorage.removeItem(Y),null)}catch(o){return console.error("Error loading from cache:",o),null}},[l]),T=x.useCallback(o=>{try{const p={apps:o,timestamp:Date.now()};localStorage.setItem(Y,JSON.stringify(p))}catch(p){console.error("Error saving to cache:",p)}},[]),y=x.useCallback(async()=>{t.current&&t.current.abort(),t.current=new AbortController;try{d(!0),b(null);const o=await fetch(`${c}/api/apps`,{signal:t.current.signal,headers:{Accept:"application/json"}});if(!o.ok)throw new Error(`HTTP error! status: ${o.status}`);const p=await o.json();i(p.apps),T(p.apps),b(null)}catch(o){if(o instanceof Error&&o.name==="AbortError")return;const p=o instanceof Error?o.message:"Failed to fetch apps";b(p),console.error("Error fetching apps:",o);const w=_();w&&i(w)}finally{d(!1)}},[c,_,T]);return x.useEffect(()=>{const o=_();return o&&(i(o),d(!1)),y(),f>0&&(v.current=window.setInterval(()=>{y()},f)),()=>{v.current&&window.clearInterval(v.current),t.current&&t.current.abort()}},[c,f,_,y]),{apps:u,isLoading:h,error:R,refetch:y}}function X({apiUrl:c,open:E,onClose:f,buttonRef:l,refetchInterval:u,cacheTime:i}){const{apps:h,isLoading:d,error:R,refetch:b}=V(c,{refetchInterval:u,cacheTime:i});return m.jsx(J,{apps:h,open:E,onClose:f,buttonRef:l,isLoading:d,error:R,onRetry:b})}exports.AppsDropdown=J;exports.AppsDropdownConnected=X;exports.default=X;exports.useAppsData=V;
7
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../node_modules/react/cjs/react-jsx-runtime.production.js","../node_modules/react/cjs/react-jsx-runtime.development.js","../node_modules/react/jsx-runtime.js","../src/AppsDropdown.tsx","../src/useAppsData.ts","../src/index.tsx"],"sourcesContent":["/**\n * @license React\n * react-jsx-runtime.production.js\n *\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n\"use strict\";\nvar REACT_ELEMENT_TYPE = Symbol.for(\"react.transitional.element\"),\n REACT_FRAGMENT_TYPE = Symbol.for(\"react.fragment\");\nfunction jsxProd(type, config, maybeKey) {\n var key = null;\n void 0 !== maybeKey && (key = \"\" + maybeKey);\n void 0 !== config.key && (key = \"\" + config.key);\n if (\"key\" in config) {\n maybeKey = {};\n for (var propName in config)\n \"key\" !== propName && (maybeKey[propName] = config[propName]);\n } else maybeKey = config;\n config = maybeKey.ref;\n return {\n $$typeof: REACT_ELEMENT_TYPE,\n type: type,\n key: key,\n ref: void 0 !== config ? config : null,\n props: maybeKey\n };\n}\nexports.Fragment = REACT_FRAGMENT_TYPE;\nexports.jsx = jsxProd;\nexports.jsxs = jsxProd;\n","/**\n * @license React\n * react-jsx-runtime.development.js\n *\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n\"use strict\";\n\"production\" !== process.env.NODE_ENV &&\n (function () {\n function getComponentNameFromType(type) {\n if (null == type) return null;\n if (\"function\" === typeof type)\n return type.$$typeof === REACT_CLIENT_REFERENCE\n ? null\n : type.displayName || type.name || null;\n if (\"string\" === typeof type) return type;\n switch (type) {\n case REACT_FRAGMENT_TYPE:\n return \"Fragment\";\n case REACT_PROFILER_TYPE:\n return \"Profiler\";\n case REACT_STRICT_MODE_TYPE:\n return \"StrictMode\";\n case REACT_SUSPENSE_TYPE:\n return \"Suspense\";\n case REACT_SUSPENSE_LIST_TYPE:\n return \"SuspenseList\";\n case REACT_ACTIVITY_TYPE:\n return \"Activity\";\n }\n if (\"object\" === typeof type)\n switch (\n (\"number\" === typeof type.tag &&\n console.error(\n \"Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue.\"\n ),\n type.$$typeof)\n ) {\n case REACT_PORTAL_TYPE:\n return \"Portal\";\n case REACT_CONTEXT_TYPE:\n return type.displayName || \"Context\";\n case REACT_CONSUMER_TYPE:\n return (type._context.displayName || \"Context\") + \".Consumer\";\n case REACT_FORWARD_REF_TYPE:\n var innerType = type.render;\n type = type.displayName;\n type ||\n ((type = innerType.displayName || innerType.name || \"\"),\n (type = \"\" !== type ? \"ForwardRef(\" + type + \")\" : \"ForwardRef\"));\n return type;\n case REACT_MEMO_TYPE:\n return (\n (innerType = type.displayName || null),\n null !== innerType\n ? innerType\n : getComponentNameFromType(type.type) || \"Memo\"\n );\n case REACT_LAZY_TYPE:\n innerType = type._payload;\n type = type._init;\n try {\n return getComponentNameFromType(type(innerType));\n } catch (x) {}\n }\n return null;\n }\n function testStringCoercion(value) {\n return \"\" + value;\n }\n function checkKeyStringCoercion(value) {\n try {\n testStringCoercion(value);\n var JSCompiler_inline_result = !1;\n } catch (e) {\n JSCompiler_inline_result = !0;\n }\n if (JSCompiler_inline_result) {\n JSCompiler_inline_result = console;\n var JSCompiler_temp_const = JSCompiler_inline_result.error;\n var JSCompiler_inline_result$jscomp$0 =\n (\"function\" === typeof Symbol &&\n Symbol.toStringTag &&\n value[Symbol.toStringTag]) ||\n value.constructor.name ||\n \"Object\";\n JSCompiler_temp_const.call(\n JSCompiler_inline_result,\n \"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.\",\n JSCompiler_inline_result$jscomp$0\n );\n return testStringCoercion(value);\n }\n }\n function getTaskName(type) {\n if (type === REACT_FRAGMENT_TYPE) return \"<>\";\n if (\n \"object\" === typeof type &&\n null !== type &&\n type.$$typeof === REACT_LAZY_TYPE\n )\n return \"<...>\";\n try {\n var name = getComponentNameFromType(type);\n return name ? \"<\" + name + \">\" : \"<...>\";\n } catch (x) {\n return \"<...>\";\n }\n }\n function getOwner() {\n var dispatcher = ReactSharedInternals.A;\n return null === dispatcher ? null : dispatcher.getOwner();\n }\n function UnknownOwner() {\n return Error(\"react-stack-top-frame\");\n }\n function hasValidKey(config) {\n if (hasOwnProperty.call(config, \"key\")) {\n var getter = Object.getOwnPropertyDescriptor(config, \"key\").get;\n if (getter && getter.isReactWarning) return !1;\n }\n return void 0 !== config.key;\n }\n function defineKeyPropWarningGetter(props, displayName) {\n function warnAboutAccessingKey() {\n specialPropKeyWarningShown ||\n ((specialPropKeyWarningShown = !0),\n console.error(\n \"%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)\",\n displayName\n ));\n }\n warnAboutAccessingKey.isReactWarning = !0;\n Object.defineProperty(props, \"key\", {\n get: warnAboutAccessingKey,\n configurable: !0\n });\n }\n function elementRefGetterWithDeprecationWarning() {\n var componentName = getComponentNameFromType(this.type);\n didWarnAboutElementRef[componentName] ||\n ((didWarnAboutElementRef[componentName] = !0),\n console.error(\n \"Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.\"\n ));\n componentName = this.props.ref;\n return void 0 !== componentName ? componentName : null;\n }\n function ReactElement(type, key, props, owner, debugStack, debugTask) {\n var refProp = props.ref;\n type = {\n $$typeof: REACT_ELEMENT_TYPE,\n type: type,\n key: key,\n props: props,\n _owner: owner\n };\n null !== (void 0 !== refProp ? refProp : null)\n ? Object.defineProperty(type, \"ref\", {\n enumerable: !1,\n get: elementRefGetterWithDeprecationWarning\n })\n : Object.defineProperty(type, \"ref\", { enumerable: !1, value: null });\n type._store = {};\n Object.defineProperty(type._store, \"validated\", {\n configurable: !1,\n enumerable: !1,\n writable: !0,\n value: 0\n });\n Object.defineProperty(type, \"_debugInfo\", {\n configurable: !1,\n enumerable: !1,\n writable: !0,\n value: null\n });\n Object.defineProperty(type, \"_debugStack\", {\n configurable: !1,\n enumerable: !1,\n writable: !0,\n value: debugStack\n });\n Object.defineProperty(type, \"_debugTask\", {\n configurable: !1,\n enumerable: !1,\n writable: !0,\n value: debugTask\n });\n Object.freeze && (Object.freeze(type.props), Object.freeze(type));\n return type;\n }\n function jsxDEVImpl(\n type,\n config,\n maybeKey,\n isStaticChildren,\n debugStack,\n debugTask\n ) {\n var children = config.children;\n if (void 0 !== children)\n if (isStaticChildren)\n if (isArrayImpl(children)) {\n for (\n isStaticChildren = 0;\n isStaticChildren < children.length;\n isStaticChildren++\n )\n validateChildKeys(children[isStaticChildren]);\n Object.freeze && Object.freeze(children);\n } else\n console.error(\n \"React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.\"\n );\n else validateChildKeys(children);\n if (hasOwnProperty.call(config, \"key\")) {\n children = getComponentNameFromType(type);\n var keys = Object.keys(config).filter(function (k) {\n return \"key\" !== k;\n });\n isStaticChildren =\n 0 < keys.length\n ? \"{key: someKey, \" + keys.join(\": ..., \") + \": ...}\"\n : \"{key: someKey}\";\n didWarnAboutKeySpread[children + isStaticChildren] ||\n ((keys =\n 0 < keys.length ? \"{\" + keys.join(\": ..., \") + \": ...}\" : \"{}\"),\n console.error(\n 'A props object containing a \"key\" prop is being spread into JSX:\\n let props = %s;\\n <%s {...props} />\\nReact keys must be passed directly to JSX without using spread:\\n let props = %s;\\n <%s key={someKey} {...props} />',\n isStaticChildren,\n children,\n keys,\n children\n ),\n (didWarnAboutKeySpread[children + isStaticChildren] = !0));\n }\n children = null;\n void 0 !== maybeKey &&\n (checkKeyStringCoercion(maybeKey), (children = \"\" + maybeKey));\n hasValidKey(config) &&\n (checkKeyStringCoercion(config.key), (children = \"\" + config.key));\n if (\"key\" in config) {\n maybeKey = {};\n for (var propName in config)\n \"key\" !== propName && (maybeKey[propName] = config[propName]);\n } else maybeKey = config;\n children &&\n defineKeyPropWarningGetter(\n maybeKey,\n \"function\" === typeof type\n ? type.displayName || type.name || \"Unknown\"\n : type\n );\n return ReactElement(\n type,\n children,\n maybeKey,\n getOwner(),\n debugStack,\n debugTask\n );\n }\n function validateChildKeys(node) {\n isValidElement(node)\n ? node._store && (node._store.validated = 1)\n : \"object\" === typeof node &&\n null !== node &&\n node.$$typeof === REACT_LAZY_TYPE &&\n (\"fulfilled\" === node._payload.status\n ? isValidElement(node._payload.value) &&\n node._payload.value._store &&\n (node._payload.value._store.validated = 1)\n : node._store && (node._store.validated = 1));\n }\n function isValidElement(object) {\n return (\n \"object\" === typeof object &&\n null !== object &&\n object.$$typeof === REACT_ELEMENT_TYPE\n );\n }\n var React = require(\"react\"),\n REACT_ELEMENT_TYPE = Symbol.for(\"react.transitional.element\"),\n REACT_PORTAL_TYPE = Symbol.for(\"react.portal\"),\n REACT_FRAGMENT_TYPE = Symbol.for(\"react.fragment\"),\n REACT_STRICT_MODE_TYPE = Symbol.for(\"react.strict_mode\"),\n REACT_PROFILER_TYPE = Symbol.for(\"react.profiler\"),\n REACT_CONSUMER_TYPE = Symbol.for(\"react.consumer\"),\n REACT_CONTEXT_TYPE = Symbol.for(\"react.context\"),\n REACT_FORWARD_REF_TYPE = Symbol.for(\"react.forward_ref\"),\n REACT_SUSPENSE_TYPE = Symbol.for(\"react.suspense\"),\n REACT_SUSPENSE_LIST_TYPE = Symbol.for(\"react.suspense_list\"),\n REACT_MEMO_TYPE = Symbol.for(\"react.memo\"),\n REACT_LAZY_TYPE = Symbol.for(\"react.lazy\"),\n REACT_ACTIVITY_TYPE = Symbol.for(\"react.activity\"),\n REACT_CLIENT_REFERENCE = Symbol.for(\"react.client.reference\"),\n ReactSharedInternals =\n React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,\n hasOwnProperty = Object.prototype.hasOwnProperty,\n isArrayImpl = Array.isArray,\n createTask = console.createTask\n ? console.createTask\n : function () {\n return null;\n };\n React = {\n react_stack_bottom_frame: function (callStackForError) {\n return callStackForError();\n }\n };\n var specialPropKeyWarningShown;\n var didWarnAboutElementRef = {};\n var unknownOwnerDebugStack = React.react_stack_bottom_frame.bind(\n React,\n UnknownOwner\n )();\n var unknownOwnerDebugTask = createTask(getTaskName(UnknownOwner));\n var didWarnAboutKeySpread = {};\n exports.Fragment = REACT_FRAGMENT_TYPE;\n exports.jsx = function (type, config, maybeKey) {\n var trackActualOwner =\n 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;\n return jsxDEVImpl(\n type,\n config,\n maybeKey,\n !1,\n trackActualOwner\n ? Error(\"react-stack-top-frame\")\n : unknownOwnerDebugStack,\n trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask\n );\n };\n exports.jsxs = function (type, config, maybeKey) {\n var trackActualOwner =\n 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;\n return jsxDEVImpl(\n type,\n config,\n maybeKey,\n !0,\n trackActualOwner\n ? Error(\"react-stack-top-frame\")\n : unknownOwnerDebugStack,\n trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask\n );\n };\n })();\n","'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n module.exports = require('./cjs/react-jsx-runtime.production.js');\n} else {\n module.exports = require('./cjs/react-jsx-runtime.development.js');\n}\n","import { useEffect, useRef, useState, useLayoutEffect } from 'react'\nimport { Box, Link, Typography, CircularProgress } from '@mui/material'\nimport { motion, AnimatePresence } from 'framer-motion'\nimport type { AppsDropdownProps } from './types'\n\nexport function AppsDropdown({\n apps,\n open,\n onClose,\n buttonRef,\n isLoading = false,\n error = null,\n onRetry\n}: AppsDropdownProps) {\n const dropdownRef = useRef<HTMLDivElement>(null)\n const [topPosition, setTopPosition] = useState('64px')\n\n useLayoutEffect(() => {\n if (open && buttonRef?.current) {\n const rect = buttonRef.current.getBoundingClientRect()\n setTopPosition(`${rect.bottom + 8}px`)\n }\n }, [open, buttonRef])\n\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (\n dropdownRef.current &&\n !dropdownRef.current.contains(event.target as Node) &&\n buttonRef?.current &&\n !buttonRef.current.contains(event.target as Node)\n ) {\n onClose()\n }\n }\n\n if (open) {\n document.addEventListener('mousedown', handleClickOutside)\n }\n\n return () => {\n document.removeEventListener('mousedown', handleClickOutside)\n }\n }, [open, onClose, buttonRef])\n\n const handleAppClick = (url: string) => {\n window.open(url, '_blank')\n onClose()\n }\n\n return (\n <AnimatePresence>\n {open && (\n <motion.div\n ref={dropdownRef}\n initial={{\n opacity: 0,\n scaleX: 0.6,\n scaleY: 0.6,\n y: -8,\n }}\n animate={{\n opacity: 1,\n scaleX: 1,\n scaleY: 1,\n y: 0,\n }}\n exit={{\n opacity: 0,\n scaleX: 0.6,\n scaleY: 0.6,\n y: -8,\n }}\n transition={{\n duration: 0.18,\n ease: 'easeOut',\n }}\n style={{\n position: 'absolute',\n top: topPosition,\n right: '16px',\n zIndex: 1000,\n transformOrigin: 'top right',\n }}\n >\n <Box\n sx={{\n bgcolor: '#E8F0FE',\n borderRadius: '8px',\n boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)',\n p: 2,\n width: '320px',\n minHeight: '100px',\n }}\n onClick={(e) => e.stopPropagation()}\n >\n {isLoading && apps.length === 0 && (\n <Box\n sx={{\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n minHeight: '100px',\n }}\n >\n <CircularProgress size={32} />\n </Box>\n )}\n\n {error && apps.length === 0 && (\n <Box\n sx={{\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n minHeight: '100px',\n gap: 1,\n }}\n >\n <Typography\n sx={{\n fontSize: '0.875rem',\n color: '#ea4335',\n textAlign: 'center',\n }}\n >\n Failed to load apps\n </Typography>\n {onRetry && (\n <Link\n component=\"button\"\n onClick={onRetry}\n sx={{\n fontSize: '0.875rem',\n color: '#1a73e8',\n cursor: 'pointer',\n textDecoration: 'underline',\n }}\n >\n Retry\n </Link>\n )}\n </Box>\n )}\n\n {apps.length > 0 && (\n <Box\n sx={{\n display: 'grid',\n gridTemplateColumns: 'repeat(3, 1fr)',\n gap: 1,\n }}\n >\n {apps.map((app) => (\n <Link\n key={app.id}\n onClick={() => handleAppClick(app.url)}\n sx={{\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n minHeight: '100px',\n p: 1.5,\n borderRadius: '12px',\n cursor: 'pointer',\n textDecoration: 'none',\n transition: 'background-color 200ms',\n '&:hover': {\n bgcolor: '#f1f3f4',\n },\n }}\n title={app.description}\n >\n <Box sx={{ pb: 1 }}>\n {app.iconUrl ? (\n <Box\n component=\"img\"\n src={app.iconUrl}\n alt={app.name}\n sx={{\n width: '32px',\n height: '32px',\n objectFit: 'contain',\n }}\n />\n ) : (\n <Box\n sx={{\n width: '32px',\n height: '32px',\n borderRadius: '6px',\n bgcolor: app.color || '#4285f4',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: '1.5rem',\n }}\n >\n {app.name.charAt(0)}\n </Box>\n )}\n </Box>\n <Typography\n sx={{\n fontSize: '0.75rem',\n fontWeight: 500,\n color: '#202124',\n textAlign: 'center',\n lineHeight: 1.2,\n }}\n >\n {app.name}\n </Typography>\n </Link>\n ))}\n </Box>\n )}\n </Box>\n </motion.div>\n )}\n </AnimatePresence>\n )\n}\n","import { useState, useEffect, useCallback, useRef } from 'react'\nimport type { App, AppsResponse, UseAppsDataOptions, UseAppsDataReturn } from './types'\n\nconst CACHE_KEY = 'spry_apps_cache'\nconst DEFAULT_REFETCH_INTERVAL = 5 * 60 * 1000 // 5 minutes\nconst DEFAULT_CACHE_TIME = 5 * 60 * 1000 // 5 minutes\n\ninterface CacheData {\n apps: App[]\n timestamp: number\n}\n\nexport function useAppsData(\n apiUrl: string,\n options: UseAppsDataOptions = {}\n): UseAppsDataReturn {\n const {\n refetchInterval = DEFAULT_REFETCH_INTERVAL,\n cacheTime = DEFAULT_CACHE_TIME\n } = options\n\n const [apps, setApps] = useState<App[]>([])\n const [isLoading, setIsLoading] = useState(true)\n const [error, setError] = useState<string | null>(null)\n const intervalRef = useRef<number | null>(null)\n const abortControllerRef = useRef<AbortController | null>(null)\n\n // Load from cache\n const loadFromCache = useCallback((): App[] | null => {\n try {\n const cached = localStorage.getItem(CACHE_KEY)\n if (!cached) return null\n\n const data: CacheData = JSON.parse(cached)\n const now = Date.now()\n\n if (now - data.timestamp < cacheTime) {\n return data.apps\n }\n\n // Cache expired, remove it\n localStorage.removeItem(CACHE_KEY)\n return null\n } catch (error) {\n console.error('Error loading from cache:', error)\n return null\n }\n }, [cacheTime])\n\n // Save to cache\n const saveToCache = useCallback((apps: App[]) => {\n try {\n const data: CacheData = {\n apps,\n timestamp: Date.now()\n }\n localStorage.setItem(CACHE_KEY, JSON.stringify(data))\n } catch (error) {\n console.error('Error saving to cache:', error)\n }\n }, [])\n\n // Fetch apps from API\n const fetchApps = useCallback(async () => {\n // Cancel previous request if still pending\n if (abortControllerRef.current) {\n abortControllerRef.current.abort()\n }\n\n // Create new abort controller\n abortControllerRef.current = new AbortController()\n\n try {\n setIsLoading(true)\n setError(null)\n\n const response = await fetch(`${apiUrl}/api/apps`, {\n signal: abortControllerRef.current.signal,\n headers: {\n 'Accept': 'application/json'\n }\n })\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`)\n }\n\n const data: AppsResponse = await response.json()\n setApps(data.apps)\n saveToCache(data.apps)\n setError(null)\n } catch (err) {\n // Don't set error if request was aborted\n if (err instanceof Error && err.name === 'AbortError') {\n return\n }\n\n const errorMessage = err instanceof Error ? err.message : 'Failed to fetch apps'\n setError(errorMessage)\n console.error('Error fetching apps:', err)\n\n // Try to use cached data on error\n const cachedApps = loadFromCache()\n if (cachedApps) {\n setApps(cachedApps)\n }\n } finally {\n setIsLoading(false)\n }\n }, [apiUrl, loadFromCache, saveToCache])\n\n // Initial load\n useEffect(() => {\n // Try to load from cache first\n const cachedApps = loadFromCache()\n if (cachedApps) {\n setApps(cachedApps)\n setIsLoading(false)\n }\n\n // Fetch fresh data\n fetchApps()\n\n // Set up refetch interval if specified\n if (refetchInterval > 0) {\n intervalRef.current = window.setInterval(() => {\n fetchApps()\n }, refetchInterval)\n }\n\n // Cleanup\n return () => {\n if (intervalRef.current) {\n window.clearInterval(intervalRef.current)\n }\n if (abortControllerRef.current) {\n abortControllerRef.current.abort()\n }\n }\n }, [apiUrl, refetchInterval, loadFromCache, fetchApps])\n\n return {\n apps,\n isLoading,\n error,\n refetch: fetchApps\n }\n}\n","import { AppsDropdown } from './AppsDropdown'\nimport { useAppsData } from './useAppsData'\nimport type { AppsDropdownConnectedProps } from './types'\n\n/**\n * AppsDropdownConnected component that automatically fetches apps from API\n * \n * @param apiUrl - Base URL of the Spry Apps API (e.g., \"http://localhost:3002\")\n * @param open - Whether the dropdown is open\n * @param onClose - Callback when dropdown should close\n * @param buttonRef - Ref to the button that triggers the dropdown (for positioning)\n * @param refetchInterval - How often to refetch apps in ms (default: 5 minutes)\n * @param cacheTime - How long to cache apps in ms (default: 5 minutes)\n */\nexport function AppsDropdownConnected({\n apiUrl,\n open,\n onClose,\n buttonRef,\n refetchInterval,\n cacheTime\n}: AppsDropdownConnectedProps) {\n const { apps, isLoading, error, refetch } = useAppsData(apiUrl, {\n refetchInterval,\n cacheTime\n })\n\n return (\n <AppsDropdown\n apps={apps}\n open={open}\n onClose={onClose}\n buttonRef={buttonRef}\n isLoading={isLoading}\n error={error}\n onRetry={refetch}\n />\n )\n}\n\n// Named exports\nexport { AppsDropdown } from './AppsDropdown'\nexport { useAppsData } from './useAppsData'\nexport * from './types'\n\n// Default export\nexport default AppsDropdownConnected\n"],"names":["REACT_ELEMENT_TYPE","REACT_FRAGMENT_TYPE","jsxProd","type","config","maybeKey","key","propName","reactJsxRuntime_production","getComponentNameFromType","REACT_CLIENT_REFERENCE","REACT_PROFILER_TYPE","REACT_STRICT_MODE_TYPE","REACT_SUSPENSE_TYPE","REACT_SUSPENSE_LIST_TYPE","REACT_ACTIVITY_TYPE","REACT_PORTAL_TYPE","REACT_CONTEXT_TYPE","REACT_CONSUMER_TYPE","REACT_FORWARD_REF_TYPE","innerType","REACT_MEMO_TYPE","REACT_LAZY_TYPE","testStringCoercion","value","checkKeyStringCoercion","JSCompiler_inline_result","JSCompiler_temp_const","JSCompiler_inline_result$jscomp$0","getTaskName","name","getOwner","dispatcher","ReactSharedInternals","UnknownOwner","hasValidKey","hasOwnProperty","getter","defineKeyPropWarningGetter","props","displayName","warnAboutAccessingKey","specialPropKeyWarningShown","elementRefGetterWithDeprecationWarning","componentName","didWarnAboutElementRef","ReactElement","owner","debugStack","debugTask","refProp","jsxDEVImpl","isStaticChildren","children","isArrayImpl","validateChildKeys","keys","k","didWarnAboutKeySpread","node","isValidElement","object","React","require$$0","createTask","callStackForError","unknownOwnerDebugStack","unknownOwnerDebugTask","reactJsxRuntime_development","trackActualOwner","jsxRuntimeModule","require$$1","AppsDropdown","apps","open","onClose","buttonRef","isLoading","error","onRetry","dropdownRef","useRef","topPosition","setTopPosition","useState","useLayoutEffect","rect","useEffect","handleClickOutside","event","handleAppClick","url","jsx","AnimatePresence","motion","jsxs","Box","e","CircularProgress","Typography","Link","app","CACHE_KEY","DEFAULT_REFETCH_INTERVAL","DEFAULT_CACHE_TIME","useAppsData","apiUrl","options","refetchInterval","cacheTime","setApps","setIsLoading","setError","intervalRef","abortControllerRef","loadFromCache","useCallback","cached","data","saveToCache","fetchApps","response","err","errorMessage","cachedApps","AppsDropdownConnected","refetch"],"mappings":"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","x_google_ignoreList":[0,1,2]}
@@ -0,0 +1,16 @@
1
+ import type { AppsDropdownConnectedProps } from './types';
2
+ /**
3
+ * AppsDropdownConnected component that automatically fetches apps from API
4
+ *
5
+ * @param apiUrl - Base URL of the Spry Apps API (e.g., "http://localhost:3002")
6
+ * @param open - Whether the dropdown is open
7
+ * @param onClose - Callback when dropdown should close
8
+ * @param buttonRef - Ref to the button that triggers the dropdown (for positioning)
9
+ * @param refetchInterval - How often to refetch apps in ms (default: 5 minutes)
10
+ * @param cacheTime - How long to cache apps in ms (default: 5 minutes)
11
+ */
12
+ export declare function AppsDropdownConnected({ apiUrl, open, onClose, buttonRef, refetchInterval, cacheTime }: AppsDropdownConnectedProps): import("react/jsx-runtime").JSX.Element;
13
+ export { AppsDropdown } from './AppsDropdown';
14
+ export { useAppsData } from './useAppsData';
15
+ export * from './types';
16
+ export default AppsDropdownConnected;
package/dist/index.js ADDED
@@ -0,0 +1,564 @@
1
+ import ie, { useRef as L, useState as O, useLayoutEffect as le, useEffect as B, useCallback as Y } from "react";
2
+ import { Box as T, CircularProgress as ue, Typography as J, Link as V } from "@mui/material";
3
+ import { AnimatePresence as fe, motion as de } from "framer-motion";
4
+ var S = { exports: {} }, A = {};
5
+ var q;
6
+ function pe() {
7
+ if (q) return A;
8
+ q = 1;
9
+ var c = /* @__PURE__ */ Symbol.for("react.transitional.element"), E = /* @__PURE__ */ Symbol.for("react.fragment");
10
+ function f(l, u, i) {
11
+ var x = null;
12
+ if (i !== void 0 && (x = "" + i), u.key !== void 0 && (x = "" + u.key), "key" in u) {
13
+ i = {};
14
+ for (var d in u)
15
+ d !== "key" && (i[d] = u[d]);
16
+ } else i = u;
17
+ return u = i.ref, {
18
+ $$typeof: c,
19
+ type: l,
20
+ key: x,
21
+ ref: u !== void 0 ? u : null,
22
+ props: i
23
+ };
24
+ }
25
+ return A.Fragment = E, A.jsx = f, A.jsxs = f, A;
26
+ }
27
+ var j = {};
28
+ var X;
29
+ function me() {
30
+ return X || (X = 1, process.env.NODE_ENV !== "production" && (function() {
31
+ function c(e) {
32
+ if (e == null) return null;
33
+ if (typeof e == "function")
34
+ return e.$$typeof === ae ? null : e.displayName || e.name || null;
35
+ if (typeof e == "string") return e;
36
+ switch (e) {
37
+ case p:
38
+ return "Fragment";
39
+ case Z:
40
+ return "Profiler";
41
+ case w:
42
+ return "StrictMode";
43
+ case re:
44
+ return "Suspense";
45
+ case te:
46
+ return "SuspenseList";
47
+ case oe:
48
+ return "Activity";
49
+ }
50
+ if (typeof e == "object")
51
+ switch (typeof e.tag == "number" && console.error(
52
+ "Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."
53
+ ), e.$$typeof) {
54
+ case o:
55
+ return "Portal";
56
+ case K:
57
+ return e.displayName || "Context";
58
+ case Q:
59
+ return (e._context.displayName || "Context") + ".Consumer";
60
+ case ee:
61
+ var r = e.render;
62
+ return e = e.displayName, e || (e = r.displayName || r.name || "", e = e !== "" ? "ForwardRef(" + e + ")" : "ForwardRef"), e;
63
+ case ne:
64
+ return r = e.displayName || null, r !== null ? r : c(e.type) || "Memo";
65
+ case C:
66
+ r = e._payload, e = e._init;
67
+ try {
68
+ return c(e(r));
69
+ } catch {
70
+ }
71
+ }
72
+ return null;
73
+ }
74
+ function E(e) {
75
+ return "" + e;
76
+ }
77
+ function f(e) {
78
+ try {
79
+ E(e);
80
+ var r = !1;
81
+ } catch {
82
+ r = !0;
83
+ }
84
+ if (r) {
85
+ r = console;
86
+ var n = r.error, a = typeof Symbol == "function" && Symbol.toStringTag && e[Symbol.toStringTag] || e.constructor.name || "Object";
87
+ return n.call(
88
+ r,
89
+ "The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",
90
+ a
91
+ ), E(e);
92
+ }
93
+ }
94
+ function l(e) {
95
+ if (e === p) return "<>";
96
+ if (typeof e == "object" && e !== null && e.$$typeof === C)
97
+ return "<...>";
98
+ try {
99
+ var r = c(e);
100
+ return r ? "<" + r + ">" : "<...>";
101
+ } catch {
102
+ return "<...>";
103
+ }
104
+ }
105
+ function u() {
106
+ var e = P.A;
107
+ return e === null ? null : e.getOwner();
108
+ }
109
+ function i() {
110
+ return Error("react-stack-top-frame");
111
+ }
112
+ function x(e) {
113
+ if ($.call(e, "key")) {
114
+ var r = Object.getOwnPropertyDescriptor(e, "key").get;
115
+ if (r && r.isReactWarning) return !1;
116
+ }
117
+ return e.key !== void 0;
118
+ }
119
+ function d(e, r) {
120
+ function n() {
121
+ z || (z = !0, console.error(
122
+ "%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",
123
+ r
124
+ ));
125
+ }
126
+ n.isReactWarning = !0, Object.defineProperty(e, "key", {
127
+ get: n,
128
+ configurable: !0
129
+ });
130
+ }
131
+ function b() {
132
+ var e = c(this.type);
133
+ return M[e] || (M[e] = !0, console.error(
134
+ "Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release."
135
+ )), e = this.props.ref, e !== void 0 ? e : null;
136
+ }
137
+ function g(e, r, n, a, k, I) {
138
+ var s = n.ref;
139
+ return e = {
140
+ $$typeof: R,
141
+ type: e,
142
+ key: r,
143
+ props: n,
144
+ _owner: a
145
+ }, (s !== void 0 ? s : null) !== null ? Object.defineProperty(e, "ref", {
146
+ enumerable: !1,
147
+ get: b
148
+ }) : Object.defineProperty(e, "ref", { enumerable: !1, value: null }), e._store = {}, Object.defineProperty(e._store, "validated", {
149
+ configurable: !1,
150
+ enumerable: !1,
151
+ writable: !0,
152
+ value: 0
153
+ }), Object.defineProperty(e, "_debugInfo", {
154
+ configurable: !1,
155
+ enumerable: !1,
156
+ writable: !0,
157
+ value: null
158
+ }), Object.defineProperty(e, "_debugStack", {
159
+ configurable: !1,
160
+ enumerable: !1,
161
+ writable: !0,
162
+ value: k
163
+ }), Object.defineProperty(e, "_debugTask", {
164
+ configurable: !1,
165
+ enumerable: !1,
166
+ writable: !0,
167
+ value: I
168
+ }), Object.freeze && (Object.freeze(e.props), Object.freeze(e)), e;
169
+ }
170
+ function _(e, r, n, a, k, I) {
171
+ var s = r.children;
172
+ if (s !== void 0)
173
+ if (a)
174
+ if (se(s)) {
175
+ for (a = 0; a < s.length; a++)
176
+ t(s[a]);
177
+ Object.freeze && Object.freeze(s);
178
+ } else
179
+ console.error(
180
+ "React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead."
181
+ );
182
+ else t(s);
183
+ if ($.call(r, "key")) {
184
+ s = c(e);
185
+ var y = Object.keys(r).filter(function(ce) {
186
+ return ce !== "key";
187
+ });
188
+ a = 0 < y.length ? "{key: someKey, " + y.join(": ..., ") + ": ...}" : "{key: someKey}", H[s + a] || (y = 0 < y.length ? "{" + y.join(": ..., ") + ": ...}" : "{}", console.error(
189
+ `A props object containing a "key" prop is being spread into JSX:
190
+ let props = %s;
191
+ <%s {...props} />
192
+ React keys must be passed directly to JSX without using spread:
193
+ let props = %s;
194
+ <%s key={someKey} {...props} />`,
195
+ a,
196
+ s,
197
+ y,
198
+ s
199
+ ), H[s + a] = !0);
200
+ }
201
+ if (s = null, n !== void 0 && (f(n), s = "" + n), x(r) && (f(r.key), s = "" + r.key), "key" in r) {
202
+ n = {};
203
+ for (var D in r)
204
+ D !== "key" && (n[D] = r[D]);
205
+ } else n = r;
206
+ return s && d(
207
+ n,
208
+ typeof e == "function" ? e.displayName || e.name || "Unknown" : e
209
+ ), g(
210
+ e,
211
+ s,
212
+ n,
213
+ u(),
214
+ k,
215
+ I
216
+ );
217
+ }
218
+ function t(e) {
219
+ h(e) ? e._store && (e._store.validated = 1) : typeof e == "object" && e !== null && e.$$typeof === C && (e._payload.status === "fulfilled" ? h(e._payload.value) && e._payload.value._store && (e._payload.value._store.validated = 1) : e._store && (e._store.validated = 1));
220
+ }
221
+ function h(e) {
222
+ return typeof e == "object" && e !== null && e.$$typeof === R;
223
+ }
224
+ var v = ie, R = /* @__PURE__ */ Symbol.for("react.transitional.element"), o = /* @__PURE__ */ Symbol.for("react.portal"), p = /* @__PURE__ */ Symbol.for("react.fragment"), w = /* @__PURE__ */ Symbol.for("react.strict_mode"), Z = /* @__PURE__ */ Symbol.for("react.profiler"), Q = /* @__PURE__ */ Symbol.for("react.consumer"), K = /* @__PURE__ */ Symbol.for("react.context"), ee = /* @__PURE__ */ Symbol.for("react.forward_ref"), re = /* @__PURE__ */ Symbol.for("react.suspense"), te = /* @__PURE__ */ Symbol.for("react.suspense_list"), ne = /* @__PURE__ */ Symbol.for("react.memo"), C = /* @__PURE__ */ Symbol.for("react.lazy"), oe = /* @__PURE__ */ Symbol.for("react.activity"), ae = /* @__PURE__ */ Symbol.for("react.client.reference"), P = v.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, $ = Object.prototype.hasOwnProperty, se = Array.isArray, N = console.createTask ? console.createTask : function() {
225
+ return null;
226
+ };
227
+ v = {
228
+ react_stack_bottom_frame: function(e) {
229
+ return e();
230
+ }
231
+ };
232
+ var z, M = {}, U = v.react_stack_bottom_frame.bind(
233
+ v,
234
+ i
235
+ )(), W = N(l(i)), H = {};
236
+ j.Fragment = p, j.jsx = function(e, r, n) {
237
+ var a = 1e4 > P.recentlyCreatedOwnerStacks++;
238
+ return _(
239
+ e,
240
+ r,
241
+ n,
242
+ !1,
243
+ a ? Error("react-stack-top-frame") : U,
244
+ a ? N(l(e)) : W
245
+ );
246
+ }, j.jsxs = function(e, r, n) {
247
+ var a = 1e4 > P.recentlyCreatedOwnerStacks++;
248
+ return _(
249
+ e,
250
+ r,
251
+ n,
252
+ !0,
253
+ a ? Error("react-stack-top-frame") : U,
254
+ a ? N(l(e)) : W
255
+ );
256
+ };
257
+ })()), j;
258
+ }
259
+ var G;
260
+ function Ee() {
261
+ return G || (G = 1, process.env.NODE_ENV === "production" ? S.exports = pe() : S.exports = me()), S.exports;
262
+ }
263
+ var m = Ee();
264
+ function xe({
265
+ apps: c,
266
+ open: E,
267
+ onClose: f,
268
+ buttonRef: l,
269
+ isLoading: u = !1,
270
+ error: i = null,
271
+ onRetry: x
272
+ }) {
273
+ const d = L(null), [b, g] = O("64px");
274
+ le(() => {
275
+ if (E && l?.current) {
276
+ const t = l.current.getBoundingClientRect();
277
+ g(`${t.bottom + 8}px`);
278
+ }
279
+ }, [E, l]), B(() => {
280
+ const t = (h) => {
281
+ d.current && !d.current.contains(h.target) && l?.current && !l.current.contains(h.target) && f();
282
+ };
283
+ return E && document.addEventListener("mousedown", t), () => {
284
+ document.removeEventListener("mousedown", t);
285
+ };
286
+ }, [E, f, l]);
287
+ const _ = (t) => {
288
+ window.open(t, "_blank"), f();
289
+ };
290
+ return /* @__PURE__ */ m.jsx(fe, { children: E && /* @__PURE__ */ m.jsx(
291
+ de.div,
292
+ {
293
+ ref: d,
294
+ initial: {
295
+ opacity: 0,
296
+ scaleX: 0.6,
297
+ scaleY: 0.6,
298
+ y: -8
299
+ },
300
+ animate: {
301
+ opacity: 1,
302
+ scaleX: 1,
303
+ scaleY: 1,
304
+ y: 0
305
+ },
306
+ exit: {
307
+ opacity: 0,
308
+ scaleX: 0.6,
309
+ scaleY: 0.6,
310
+ y: -8
311
+ },
312
+ transition: {
313
+ duration: 0.18,
314
+ ease: "easeOut"
315
+ },
316
+ style: {
317
+ position: "absolute",
318
+ top: b,
319
+ right: "16px",
320
+ zIndex: 1e3,
321
+ transformOrigin: "top right"
322
+ },
323
+ children: /* @__PURE__ */ m.jsxs(
324
+ T,
325
+ {
326
+ sx: {
327
+ bgcolor: "#E8F0FE",
328
+ borderRadius: "8px",
329
+ boxShadow: "0 2px 8px rgba(0, 0, 0, 0.1)",
330
+ p: 2,
331
+ width: "320px",
332
+ minHeight: "100px"
333
+ },
334
+ onClick: (t) => t.stopPropagation(),
335
+ children: [
336
+ u && c.length === 0 && /* @__PURE__ */ m.jsx(
337
+ T,
338
+ {
339
+ sx: {
340
+ display: "flex",
341
+ justifyContent: "center",
342
+ alignItems: "center",
343
+ minHeight: "100px"
344
+ },
345
+ children: /* @__PURE__ */ m.jsx(ue, { size: 32 })
346
+ }
347
+ ),
348
+ i && c.length === 0 && /* @__PURE__ */ m.jsxs(
349
+ T,
350
+ {
351
+ sx: {
352
+ display: "flex",
353
+ flexDirection: "column",
354
+ alignItems: "center",
355
+ justifyContent: "center",
356
+ minHeight: "100px",
357
+ gap: 1
358
+ },
359
+ children: [
360
+ /* @__PURE__ */ m.jsx(
361
+ J,
362
+ {
363
+ sx: {
364
+ fontSize: "0.875rem",
365
+ color: "#ea4335",
366
+ textAlign: "center"
367
+ },
368
+ children: "Failed to load apps"
369
+ }
370
+ ),
371
+ x && /* @__PURE__ */ m.jsx(
372
+ V,
373
+ {
374
+ component: "button",
375
+ onClick: x,
376
+ sx: {
377
+ fontSize: "0.875rem",
378
+ color: "#1a73e8",
379
+ cursor: "pointer",
380
+ textDecoration: "underline"
381
+ },
382
+ children: "Retry"
383
+ }
384
+ )
385
+ ]
386
+ }
387
+ ),
388
+ c.length > 0 && /* @__PURE__ */ m.jsx(
389
+ T,
390
+ {
391
+ sx: {
392
+ display: "grid",
393
+ gridTemplateColumns: "repeat(3, 1fr)",
394
+ gap: 1
395
+ },
396
+ children: c.map((t) => /* @__PURE__ */ m.jsxs(
397
+ V,
398
+ {
399
+ onClick: () => _(t.url),
400
+ sx: {
401
+ display: "flex",
402
+ flexDirection: "column",
403
+ alignItems: "center",
404
+ justifyContent: "center",
405
+ minHeight: "100px",
406
+ p: 1.5,
407
+ borderRadius: "12px",
408
+ cursor: "pointer",
409
+ textDecoration: "none",
410
+ transition: "background-color 200ms",
411
+ "&:hover": {
412
+ bgcolor: "#f1f3f4"
413
+ }
414
+ },
415
+ title: t.description,
416
+ children: [
417
+ /* @__PURE__ */ m.jsx(T, { sx: { pb: 1 }, children: t.iconUrl ? /* @__PURE__ */ m.jsx(
418
+ T,
419
+ {
420
+ component: "img",
421
+ src: t.iconUrl,
422
+ alt: t.name,
423
+ sx: {
424
+ width: "32px",
425
+ height: "32px",
426
+ objectFit: "contain"
427
+ }
428
+ }
429
+ ) : /* @__PURE__ */ m.jsx(
430
+ T,
431
+ {
432
+ sx: {
433
+ width: "32px",
434
+ height: "32px",
435
+ borderRadius: "6px",
436
+ bgcolor: t.color || "#4285f4",
437
+ display: "flex",
438
+ alignItems: "center",
439
+ justifyContent: "center",
440
+ fontSize: "1.5rem"
441
+ },
442
+ children: t.name.charAt(0)
443
+ }
444
+ ) }),
445
+ /* @__PURE__ */ m.jsx(
446
+ J,
447
+ {
448
+ sx: {
449
+ fontSize: "0.75rem",
450
+ fontWeight: 500,
451
+ color: "#202124",
452
+ textAlign: "center",
453
+ lineHeight: 1.2
454
+ },
455
+ children: t.name
456
+ }
457
+ )
458
+ ]
459
+ },
460
+ t.id
461
+ ))
462
+ }
463
+ )
464
+ ]
465
+ }
466
+ )
467
+ }
468
+ ) });
469
+ }
470
+ const F = "spry_apps_cache", he = 300 * 1e3, ge = 300 * 1e3;
471
+ function _e(c, E = {}) {
472
+ const {
473
+ refetchInterval: f = he,
474
+ cacheTime: l = ge
475
+ } = E, [u, i] = O([]), [x, d] = O(!0), [b, g] = O(null), _ = L(null), t = L(null), h = Y(() => {
476
+ try {
477
+ const o = localStorage.getItem(F);
478
+ if (!o) return null;
479
+ const p = JSON.parse(o);
480
+ return Date.now() - p.timestamp < l ? p.apps : (localStorage.removeItem(F), null);
481
+ } catch (o) {
482
+ return console.error("Error loading from cache:", o), null;
483
+ }
484
+ }, [l]), v = Y((o) => {
485
+ try {
486
+ const p = {
487
+ apps: o,
488
+ timestamp: Date.now()
489
+ };
490
+ localStorage.setItem(F, JSON.stringify(p));
491
+ } catch (p) {
492
+ console.error("Error saving to cache:", p);
493
+ }
494
+ }, []), R = Y(async () => {
495
+ t.current && t.current.abort(), t.current = new AbortController();
496
+ try {
497
+ d(!0), g(null);
498
+ const o = await fetch(`${c}/api/apps`, {
499
+ signal: t.current.signal,
500
+ headers: {
501
+ Accept: "application/json"
502
+ }
503
+ });
504
+ if (!o.ok)
505
+ throw new Error(`HTTP error! status: ${o.status}`);
506
+ const p = await o.json();
507
+ i(p.apps), v(p.apps), g(null);
508
+ } catch (o) {
509
+ if (o instanceof Error && o.name === "AbortError")
510
+ return;
511
+ const p = o instanceof Error ? o.message : "Failed to fetch apps";
512
+ g(p), console.error("Error fetching apps:", o);
513
+ const w = h();
514
+ w && i(w);
515
+ } finally {
516
+ d(!1);
517
+ }
518
+ }, [c, h, v]);
519
+ return B(() => {
520
+ const o = h();
521
+ return o && (i(o), d(!1)), R(), f > 0 && (_.current = window.setInterval(() => {
522
+ R();
523
+ }, f)), () => {
524
+ _.current && window.clearInterval(_.current), t.current && t.current.abort();
525
+ };
526
+ }, [c, f, h, R]), {
527
+ apps: u,
528
+ isLoading: x,
529
+ error: b,
530
+ refetch: R
531
+ };
532
+ }
533
+ function Te({
534
+ apiUrl: c,
535
+ open: E,
536
+ onClose: f,
537
+ buttonRef: l,
538
+ refetchInterval: u,
539
+ cacheTime: i
540
+ }) {
541
+ const { apps: x, isLoading: d, error: b, refetch: g } = _e(c, {
542
+ refetchInterval: u,
543
+ cacheTime: i
544
+ });
545
+ return /* @__PURE__ */ m.jsx(
546
+ xe,
547
+ {
548
+ apps: x,
549
+ open: E,
550
+ onClose: f,
551
+ buttonRef: l,
552
+ isLoading: d,
553
+ error: b,
554
+ onRetry: g
555
+ }
556
+ );
557
+ }
558
+ export {
559
+ xe as AppsDropdown,
560
+ Te as AppsDropdownConnected,
561
+ Te as default,
562
+ _e as useAppsData
563
+ };
564
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../node_modules/react/cjs/react-jsx-runtime.production.js","../node_modules/react/cjs/react-jsx-runtime.development.js","../node_modules/react/jsx-runtime.js","../src/AppsDropdown.tsx","../src/useAppsData.ts","../src/index.tsx"],"sourcesContent":["/**\n * @license React\n * react-jsx-runtime.production.js\n *\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n\"use strict\";\nvar REACT_ELEMENT_TYPE = Symbol.for(\"react.transitional.element\"),\n REACT_FRAGMENT_TYPE = Symbol.for(\"react.fragment\");\nfunction jsxProd(type, config, maybeKey) {\n var key = null;\n void 0 !== maybeKey && (key = \"\" + maybeKey);\n void 0 !== config.key && (key = \"\" + config.key);\n if (\"key\" in config) {\n maybeKey = {};\n for (var propName in config)\n \"key\" !== propName && (maybeKey[propName] = config[propName]);\n } else maybeKey = config;\n config = maybeKey.ref;\n return {\n $$typeof: REACT_ELEMENT_TYPE,\n type: type,\n key: key,\n ref: void 0 !== config ? config : null,\n props: maybeKey\n };\n}\nexports.Fragment = REACT_FRAGMENT_TYPE;\nexports.jsx = jsxProd;\nexports.jsxs = jsxProd;\n","/**\n * @license React\n * react-jsx-runtime.development.js\n *\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n\"use strict\";\n\"production\" !== process.env.NODE_ENV &&\n (function () {\n function getComponentNameFromType(type) {\n if (null == type) return null;\n if (\"function\" === typeof type)\n return type.$$typeof === REACT_CLIENT_REFERENCE\n ? null\n : type.displayName || type.name || null;\n if (\"string\" === typeof type) return type;\n switch (type) {\n case REACT_FRAGMENT_TYPE:\n return \"Fragment\";\n case REACT_PROFILER_TYPE:\n return \"Profiler\";\n case REACT_STRICT_MODE_TYPE:\n return \"StrictMode\";\n case REACT_SUSPENSE_TYPE:\n return \"Suspense\";\n case REACT_SUSPENSE_LIST_TYPE:\n return \"SuspenseList\";\n case REACT_ACTIVITY_TYPE:\n return \"Activity\";\n }\n if (\"object\" === typeof type)\n switch (\n (\"number\" === typeof type.tag &&\n console.error(\n \"Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue.\"\n ),\n type.$$typeof)\n ) {\n case REACT_PORTAL_TYPE:\n return \"Portal\";\n case REACT_CONTEXT_TYPE:\n return type.displayName || \"Context\";\n case REACT_CONSUMER_TYPE:\n return (type._context.displayName || \"Context\") + \".Consumer\";\n case REACT_FORWARD_REF_TYPE:\n var innerType = type.render;\n type = type.displayName;\n type ||\n ((type = innerType.displayName || innerType.name || \"\"),\n (type = \"\" !== type ? \"ForwardRef(\" + type + \")\" : \"ForwardRef\"));\n return type;\n case REACT_MEMO_TYPE:\n return (\n (innerType = type.displayName || null),\n null !== innerType\n ? innerType\n : getComponentNameFromType(type.type) || \"Memo\"\n );\n case REACT_LAZY_TYPE:\n innerType = type._payload;\n type = type._init;\n try {\n return getComponentNameFromType(type(innerType));\n } catch (x) {}\n }\n return null;\n }\n function testStringCoercion(value) {\n return \"\" + value;\n }\n function checkKeyStringCoercion(value) {\n try {\n testStringCoercion(value);\n var JSCompiler_inline_result = !1;\n } catch (e) {\n JSCompiler_inline_result = !0;\n }\n if (JSCompiler_inline_result) {\n JSCompiler_inline_result = console;\n var JSCompiler_temp_const = JSCompiler_inline_result.error;\n var JSCompiler_inline_result$jscomp$0 =\n (\"function\" === typeof Symbol &&\n Symbol.toStringTag &&\n value[Symbol.toStringTag]) ||\n value.constructor.name ||\n \"Object\";\n JSCompiler_temp_const.call(\n JSCompiler_inline_result,\n \"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.\",\n JSCompiler_inline_result$jscomp$0\n );\n return testStringCoercion(value);\n }\n }\n function getTaskName(type) {\n if (type === REACT_FRAGMENT_TYPE) return \"<>\";\n if (\n \"object\" === typeof type &&\n null !== type &&\n type.$$typeof === REACT_LAZY_TYPE\n )\n return \"<...>\";\n try {\n var name = getComponentNameFromType(type);\n return name ? \"<\" + name + \">\" : \"<...>\";\n } catch (x) {\n return \"<...>\";\n }\n }\n function getOwner() {\n var dispatcher = ReactSharedInternals.A;\n return null === dispatcher ? null : dispatcher.getOwner();\n }\n function UnknownOwner() {\n return Error(\"react-stack-top-frame\");\n }\n function hasValidKey(config) {\n if (hasOwnProperty.call(config, \"key\")) {\n var getter = Object.getOwnPropertyDescriptor(config, \"key\").get;\n if (getter && getter.isReactWarning) return !1;\n }\n return void 0 !== config.key;\n }\n function defineKeyPropWarningGetter(props, displayName) {\n function warnAboutAccessingKey() {\n specialPropKeyWarningShown ||\n ((specialPropKeyWarningShown = !0),\n console.error(\n \"%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)\",\n displayName\n ));\n }\n warnAboutAccessingKey.isReactWarning = !0;\n Object.defineProperty(props, \"key\", {\n get: warnAboutAccessingKey,\n configurable: !0\n });\n }\n function elementRefGetterWithDeprecationWarning() {\n var componentName = getComponentNameFromType(this.type);\n didWarnAboutElementRef[componentName] ||\n ((didWarnAboutElementRef[componentName] = !0),\n console.error(\n \"Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.\"\n ));\n componentName = this.props.ref;\n return void 0 !== componentName ? componentName : null;\n }\n function ReactElement(type, key, props, owner, debugStack, debugTask) {\n var refProp = props.ref;\n type = {\n $$typeof: REACT_ELEMENT_TYPE,\n type: type,\n key: key,\n props: props,\n _owner: owner\n };\n null !== (void 0 !== refProp ? refProp : null)\n ? Object.defineProperty(type, \"ref\", {\n enumerable: !1,\n get: elementRefGetterWithDeprecationWarning\n })\n : Object.defineProperty(type, \"ref\", { enumerable: !1, value: null });\n type._store = {};\n Object.defineProperty(type._store, \"validated\", {\n configurable: !1,\n enumerable: !1,\n writable: !0,\n value: 0\n });\n Object.defineProperty(type, \"_debugInfo\", {\n configurable: !1,\n enumerable: !1,\n writable: !0,\n value: null\n });\n Object.defineProperty(type, \"_debugStack\", {\n configurable: !1,\n enumerable: !1,\n writable: !0,\n value: debugStack\n });\n Object.defineProperty(type, \"_debugTask\", {\n configurable: !1,\n enumerable: !1,\n writable: !0,\n value: debugTask\n });\n Object.freeze && (Object.freeze(type.props), Object.freeze(type));\n return type;\n }\n function jsxDEVImpl(\n type,\n config,\n maybeKey,\n isStaticChildren,\n debugStack,\n debugTask\n ) {\n var children = config.children;\n if (void 0 !== children)\n if (isStaticChildren)\n if (isArrayImpl(children)) {\n for (\n isStaticChildren = 0;\n isStaticChildren < children.length;\n isStaticChildren++\n )\n validateChildKeys(children[isStaticChildren]);\n Object.freeze && Object.freeze(children);\n } else\n console.error(\n \"React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.\"\n );\n else validateChildKeys(children);\n if (hasOwnProperty.call(config, \"key\")) {\n children = getComponentNameFromType(type);\n var keys = Object.keys(config).filter(function (k) {\n return \"key\" !== k;\n });\n isStaticChildren =\n 0 < keys.length\n ? \"{key: someKey, \" + keys.join(\": ..., \") + \": ...}\"\n : \"{key: someKey}\";\n didWarnAboutKeySpread[children + isStaticChildren] ||\n ((keys =\n 0 < keys.length ? \"{\" + keys.join(\": ..., \") + \": ...}\" : \"{}\"),\n console.error(\n 'A props object containing a \"key\" prop is being spread into JSX:\\n let props = %s;\\n <%s {...props} />\\nReact keys must be passed directly to JSX without using spread:\\n let props = %s;\\n <%s key={someKey} {...props} />',\n isStaticChildren,\n children,\n keys,\n children\n ),\n (didWarnAboutKeySpread[children + isStaticChildren] = !0));\n }\n children = null;\n void 0 !== maybeKey &&\n (checkKeyStringCoercion(maybeKey), (children = \"\" + maybeKey));\n hasValidKey(config) &&\n (checkKeyStringCoercion(config.key), (children = \"\" + config.key));\n if (\"key\" in config) {\n maybeKey = {};\n for (var propName in config)\n \"key\" !== propName && (maybeKey[propName] = config[propName]);\n } else maybeKey = config;\n children &&\n defineKeyPropWarningGetter(\n maybeKey,\n \"function\" === typeof type\n ? type.displayName || type.name || \"Unknown\"\n : type\n );\n return ReactElement(\n type,\n children,\n maybeKey,\n getOwner(),\n debugStack,\n debugTask\n );\n }\n function validateChildKeys(node) {\n isValidElement(node)\n ? node._store && (node._store.validated = 1)\n : \"object\" === typeof node &&\n null !== node &&\n node.$$typeof === REACT_LAZY_TYPE &&\n (\"fulfilled\" === node._payload.status\n ? isValidElement(node._payload.value) &&\n node._payload.value._store &&\n (node._payload.value._store.validated = 1)\n : node._store && (node._store.validated = 1));\n }\n function isValidElement(object) {\n return (\n \"object\" === typeof object &&\n null !== object &&\n object.$$typeof === REACT_ELEMENT_TYPE\n );\n }\n var React = require(\"react\"),\n REACT_ELEMENT_TYPE = Symbol.for(\"react.transitional.element\"),\n REACT_PORTAL_TYPE = Symbol.for(\"react.portal\"),\n REACT_FRAGMENT_TYPE = Symbol.for(\"react.fragment\"),\n REACT_STRICT_MODE_TYPE = Symbol.for(\"react.strict_mode\"),\n REACT_PROFILER_TYPE = Symbol.for(\"react.profiler\"),\n REACT_CONSUMER_TYPE = Symbol.for(\"react.consumer\"),\n REACT_CONTEXT_TYPE = Symbol.for(\"react.context\"),\n REACT_FORWARD_REF_TYPE = Symbol.for(\"react.forward_ref\"),\n REACT_SUSPENSE_TYPE = Symbol.for(\"react.suspense\"),\n REACT_SUSPENSE_LIST_TYPE = Symbol.for(\"react.suspense_list\"),\n REACT_MEMO_TYPE = Symbol.for(\"react.memo\"),\n REACT_LAZY_TYPE = Symbol.for(\"react.lazy\"),\n REACT_ACTIVITY_TYPE = Symbol.for(\"react.activity\"),\n REACT_CLIENT_REFERENCE = Symbol.for(\"react.client.reference\"),\n ReactSharedInternals =\n React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,\n hasOwnProperty = Object.prototype.hasOwnProperty,\n isArrayImpl = Array.isArray,\n createTask = console.createTask\n ? console.createTask\n : function () {\n return null;\n };\n React = {\n react_stack_bottom_frame: function (callStackForError) {\n return callStackForError();\n }\n };\n var specialPropKeyWarningShown;\n var didWarnAboutElementRef = {};\n var unknownOwnerDebugStack = React.react_stack_bottom_frame.bind(\n React,\n UnknownOwner\n )();\n var unknownOwnerDebugTask = createTask(getTaskName(UnknownOwner));\n var didWarnAboutKeySpread = {};\n exports.Fragment = REACT_FRAGMENT_TYPE;\n exports.jsx = function (type, config, maybeKey) {\n var trackActualOwner =\n 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;\n return jsxDEVImpl(\n type,\n config,\n maybeKey,\n !1,\n trackActualOwner\n ? Error(\"react-stack-top-frame\")\n : unknownOwnerDebugStack,\n trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask\n );\n };\n exports.jsxs = function (type, config, maybeKey) {\n var trackActualOwner =\n 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;\n return jsxDEVImpl(\n type,\n config,\n maybeKey,\n !0,\n trackActualOwner\n ? Error(\"react-stack-top-frame\")\n : unknownOwnerDebugStack,\n trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask\n );\n };\n })();\n","'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n module.exports = require('./cjs/react-jsx-runtime.production.js');\n} else {\n module.exports = require('./cjs/react-jsx-runtime.development.js');\n}\n","import { useEffect, useRef, useState, useLayoutEffect } from 'react'\nimport { Box, Link, Typography, CircularProgress } from '@mui/material'\nimport { motion, AnimatePresence } from 'framer-motion'\nimport type { AppsDropdownProps } from './types'\n\nexport function AppsDropdown({\n apps,\n open,\n onClose,\n buttonRef,\n isLoading = false,\n error = null,\n onRetry\n}: AppsDropdownProps) {\n const dropdownRef = useRef<HTMLDivElement>(null)\n const [topPosition, setTopPosition] = useState('64px')\n\n useLayoutEffect(() => {\n if (open && buttonRef?.current) {\n const rect = buttonRef.current.getBoundingClientRect()\n setTopPosition(`${rect.bottom + 8}px`)\n }\n }, [open, buttonRef])\n\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (\n dropdownRef.current &&\n !dropdownRef.current.contains(event.target as Node) &&\n buttonRef?.current &&\n !buttonRef.current.contains(event.target as Node)\n ) {\n onClose()\n }\n }\n\n if (open) {\n document.addEventListener('mousedown', handleClickOutside)\n }\n\n return () => {\n document.removeEventListener('mousedown', handleClickOutside)\n }\n }, [open, onClose, buttonRef])\n\n const handleAppClick = (url: string) => {\n window.open(url, '_blank')\n onClose()\n }\n\n return (\n <AnimatePresence>\n {open && (\n <motion.div\n ref={dropdownRef}\n initial={{\n opacity: 0,\n scaleX: 0.6,\n scaleY: 0.6,\n y: -8,\n }}\n animate={{\n opacity: 1,\n scaleX: 1,\n scaleY: 1,\n y: 0,\n }}\n exit={{\n opacity: 0,\n scaleX: 0.6,\n scaleY: 0.6,\n y: -8,\n }}\n transition={{\n duration: 0.18,\n ease: 'easeOut',\n }}\n style={{\n position: 'absolute',\n top: topPosition,\n right: '16px',\n zIndex: 1000,\n transformOrigin: 'top right',\n }}\n >\n <Box\n sx={{\n bgcolor: '#E8F0FE',\n borderRadius: '8px',\n boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)',\n p: 2,\n width: '320px',\n minHeight: '100px',\n }}\n onClick={(e) => e.stopPropagation()}\n >\n {isLoading && apps.length === 0 && (\n <Box\n sx={{\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n minHeight: '100px',\n }}\n >\n <CircularProgress size={32} />\n </Box>\n )}\n\n {error && apps.length === 0 && (\n <Box\n sx={{\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n minHeight: '100px',\n gap: 1,\n }}\n >\n <Typography\n sx={{\n fontSize: '0.875rem',\n color: '#ea4335',\n textAlign: 'center',\n }}\n >\n Failed to load apps\n </Typography>\n {onRetry && (\n <Link\n component=\"button\"\n onClick={onRetry}\n sx={{\n fontSize: '0.875rem',\n color: '#1a73e8',\n cursor: 'pointer',\n textDecoration: 'underline',\n }}\n >\n Retry\n </Link>\n )}\n </Box>\n )}\n\n {apps.length > 0 && (\n <Box\n sx={{\n display: 'grid',\n gridTemplateColumns: 'repeat(3, 1fr)',\n gap: 1,\n }}\n >\n {apps.map((app) => (\n <Link\n key={app.id}\n onClick={() => handleAppClick(app.url)}\n sx={{\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n minHeight: '100px',\n p: 1.5,\n borderRadius: '12px',\n cursor: 'pointer',\n textDecoration: 'none',\n transition: 'background-color 200ms',\n '&:hover': {\n bgcolor: '#f1f3f4',\n },\n }}\n title={app.description}\n >\n <Box sx={{ pb: 1 }}>\n {app.iconUrl ? (\n <Box\n component=\"img\"\n src={app.iconUrl}\n alt={app.name}\n sx={{\n width: '32px',\n height: '32px',\n objectFit: 'contain',\n }}\n />\n ) : (\n <Box\n sx={{\n width: '32px',\n height: '32px',\n borderRadius: '6px',\n bgcolor: app.color || '#4285f4',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: '1.5rem',\n }}\n >\n {app.name.charAt(0)}\n </Box>\n )}\n </Box>\n <Typography\n sx={{\n fontSize: '0.75rem',\n fontWeight: 500,\n color: '#202124',\n textAlign: 'center',\n lineHeight: 1.2,\n }}\n >\n {app.name}\n </Typography>\n </Link>\n ))}\n </Box>\n )}\n </Box>\n </motion.div>\n )}\n </AnimatePresence>\n )\n}\n","import { useState, useEffect, useCallback, useRef } from 'react'\nimport type { App, AppsResponse, UseAppsDataOptions, UseAppsDataReturn } from './types'\n\nconst CACHE_KEY = 'spry_apps_cache'\nconst DEFAULT_REFETCH_INTERVAL = 5 * 60 * 1000 // 5 minutes\nconst DEFAULT_CACHE_TIME = 5 * 60 * 1000 // 5 minutes\n\ninterface CacheData {\n apps: App[]\n timestamp: number\n}\n\nexport function useAppsData(\n apiUrl: string,\n options: UseAppsDataOptions = {}\n): UseAppsDataReturn {\n const {\n refetchInterval = DEFAULT_REFETCH_INTERVAL,\n cacheTime = DEFAULT_CACHE_TIME\n } = options\n\n const [apps, setApps] = useState<App[]>([])\n const [isLoading, setIsLoading] = useState(true)\n const [error, setError] = useState<string | null>(null)\n const intervalRef = useRef<number | null>(null)\n const abortControllerRef = useRef<AbortController | null>(null)\n\n // Load from cache\n const loadFromCache = useCallback((): App[] | null => {\n try {\n const cached = localStorage.getItem(CACHE_KEY)\n if (!cached) return null\n\n const data: CacheData = JSON.parse(cached)\n const now = Date.now()\n\n if (now - data.timestamp < cacheTime) {\n return data.apps\n }\n\n // Cache expired, remove it\n localStorage.removeItem(CACHE_KEY)\n return null\n } catch (error) {\n console.error('Error loading from cache:', error)\n return null\n }\n }, [cacheTime])\n\n // Save to cache\n const saveToCache = useCallback((apps: App[]) => {\n try {\n const data: CacheData = {\n apps,\n timestamp: Date.now()\n }\n localStorage.setItem(CACHE_KEY, JSON.stringify(data))\n } catch (error) {\n console.error('Error saving to cache:', error)\n }\n }, [])\n\n // Fetch apps from API\n const fetchApps = useCallback(async () => {\n // Cancel previous request if still pending\n if (abortControllerRef.current) {\n abortControllerRef.current.abort()\n }\n\n // Create new abort controller\n abortControllerRef.current = new AbortController()\n\n try {\n setIsLoading(true)\n setError(null)\n\n const response = await fetch(`${apiUrl}/api/apps`, {\n signal: abortControllerRef.current.signal,\n headers: {\n 'Accept': 'application/json'\n }\n })\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`)\n }\n\n const data: AppsResponse = await response.json()\n setApps(data.apps)\n saveToCache(data.apps)\n setError(null)\n } catch (err) {\n // Don't set error if request was aborted\n if (err instanceof Error && err.name === 'AbortError') {\n return\n }\n\n const errorMessage = err instanceof Error ? err.message : 'Failed to fetch apps'\n setError(errorMessage)\n console.error('Error fetching apps:', err)\n\n // Try to use cached data on error\n const cachedApps = loadFromCache()\n if (cachedApps) {\n setApps(cachedApps)\n }\n } finally {\n setIsLoading(false)\n }\n }, [apiUrl, loadFromCache, saveToCache])\n\n // Initial load\n useEffect(() => {\n // Try to load from cache first\n const cachedApps = loadFromCache()\n if (cachedApps) {\n setApps(cachedApps)\n setIsLoading(false)\n }\n\n // Fetch fresh data\n fetchApps()\n\n // Set up refetch interval if specified\n if (refetchInterval > 0) {\n intervalRef.current = window.setInterval(() => {\n fetchApps()\n }, refetchInterval)\n }\n\n // Cleanup\n return () => {\n if (intervalRef.current) {\n window.clearInterval(intervalRef.current)\n }\n if (abortControllerRef.current) {\n abortControllerRef.current.abort()\n }\n }\n }, [apiUrl, refetchInterval, loadFromCache, fetchApps])\n\n return {\n apps,\n isLoading,\n error,\n refetch: fetchApps\n }\n}\n","import { AppsDropdown } from './AppsDropdown'\nimport { useAppsData } from './useAppsData'\nimport type { AppsDropdownConnectedProps } from './types'\n\n/**\n * AppsDropdownConnected component that automatically fetches apps from API\n * \n * @param apiUrl - Base URL of the Spry Apps API (e.g., \"http://localhost:3002\")\n * @param open - Whether the dropdown is open\n * @param onClose - Callback when dropdown should close\n * @param buttonRef - Ref to the button that triggers the dropdown (for positioning)\n * @param refetchInterval - How often to refetch apps in ms (default: 5 minutes)\n * @param cacheTime - How long to cache apps in ms (default: 5 minutes)\n */\nexport function AppsDropdownConnected({\n apiUrl,\n open,\n onClose,\n buttonRef,\n refetchInterval,\n cacheTime\n}: AppsDropdownConnectedProps) {\n const { apps, isLoading, error, refetch } = useAppsData(apiUrl, {\n refetchInterval,\n cacheTime\n })\n\n return (\n <AppsDropdown\n apps={apps}\n open={open}\n onClose={onClose}\n buttonRef={buttonRef}\n isLoading={isLoading}\n error={error}\n onRetry={refetch}\n />\n )\n}\n\n// Named exports\nexport { AppsDropdown } from './AppsDropdown'\nexport { useAppsData } from './useAppsData'\nexport * from './types'\n\n// Default export\nexport default AppsDropdownConnected\n"],"names":["REACT_ELEMENT_TYPE","REACT_FRAGMENT_TYPE","jsxProd","type","config","maybeKey","key","propName","reactJsxRuntime_production","getComponentNameFromType","REACT_CLIENT_REFERENCE","REACT_PROFILER_TYPE","REACT_STRICT_MODE_TYPE","REACT_SUSPENSE_TYPE","REACT_SUSPENSE_LIST_TYPE","REACT_ACTIVITY_TYPE","REACT_PORTAL_TYPE","REACT_CONTEXT_TYPE","REACT_CONSUMER_TYPE","REACT_FORWARD_REF_TYPE","innerType","REACT_MEMO_TYPE","REACT_LAZY_TYPE","testStringCoercion","value","checkKeyStringCoercion","JSCompiler_inline_result","JSCompiler_temp_const","JSCompiler_inline_result$jscomp$0","getTaskName","name","getOwner","dispatcher","ReactSharedInternals","UnknownOwner","hasValidKey","hasOwnProperty","getter","defineKeyPropWarningGetter","props","displayName","warnAboutAccessingKey","specialPropKeyWarningShown","elementRefGetterWithDeprecationWarning","componentName","didWarnAboutElementRef","ReactElement","owner","debugStack","debugTask","refProp","jsxDEVImpl","isStaticChildren","children","isArrayImpl","validateChildKeys","keys","k","didWarnAboutKeySpread","node","isValidElement","object","React","require$$0","createTask","callStackForError","unknownOwnerDebugStack","unknownOwnerDebugTask","reactJsxRuntime_development","trackActualOwner","jsxRuntimeModule","require$$1","AppsDropdown","apps","open","onClose","buttonRef","isLoading","error","onRetry","dropdownRef","useRef","topPosition","setTopPosition","useState","useLayoutEffect","rect","useEffect","handleClickOutside","event","handleAppClick","url","jsx","AnimatePresence","motion","jsxs","Box","e","CircularProgress","Typography","Link","app","CACHE_KEY","DEFAULT_REFETCH_INTERVAL","DEFAULT_CACHE_TIME","useAppsData","apiUrl","options","refetchInterval","cacheTime","setApps","setIsLoading","setError","intervalRef","abortControllerRef","loadFromCache","useCallback","cached","data","saveToCache","fetchApps","response","err","errorMessage","cachedApps","AppsDropdownConnected","refetch"],"mappings":"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","x_google_ignoreList":[0,1,2]}
@@ -0,0 +1,42 @@
1
+ export interface App {
2
+ id: string;
3
+ name: string;
4
+ description: string;
5
+ url: string;
6
+ iconUrl: string;
7
+ color: string;
8
+ order: number;
9
+ createdAt: string;
10
+ updatedAt: string;
11
+ }
12
+ export interface AppsResponse {
13
+ apps: App[];
14
+ lastUpdated: string;
15
+ }
16
+ export interface AppsDropdownProps {
17
+ apps: App[];
18
+ open: boolean;
19
+ onClose: () => void;
20
+ buttonRef?: React.RefObject<HTMLButtonElement | null>;
21
+ isLoading?: boolean;
22
+ error?: string | null;
23
+ onRetry?: () => void;
24
+ }
25
+ export interface AppsDropdownConnectedProps {
26
+ apiUrl: string;
27
+ open: boolean;
28
+ onClose: () => void;
29
+ buttonRef?: React.RefObject<HTMLButtonElement | null>;
30
+ refetchInterval?: number;
31
+ cacheTime?: number;
32
+ }
33
+ export interface UseAppsDataOptions {
34
+ refetchInterval?: number;
35
+ cacheTime?: number;
36
+ }
37
+ export interface UseAppsDataReturn {
38
+ apps: App[];
39
+ isLoading: boolean;
40
+ error: string | null;
41
+ refetch: () => Promise<void>;
42
+ }
@@ -0,0 +1,2 @@
1
+ import type { UseAppsDataOptions, UseAppsDataReturn } from './types';
2
+ export declare function useAppsData(apiUrl: string, options?: UseAppsDataOptions): UseAppsDataReturn;
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "spry-apps-dropdown",
3
+ "version": "1.0.0",
4
+ "description": "React dropdown component for displaying Spry apps with dynamic API integration",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "require": "./dist/index.cjs"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist",
18
+ "README.md"
19
+ ],
20
+ "scripts": {
21
+ "build": "vite build && tsc --emitDeclarationOnly",
22
+ "dev": "vite build --watch",
23
+ "prepublishOnly": "npm run build"
24
+ },
25
+ "keywords": [
26
+ "spry",
27
+ "apps",
28
+ "dropdown",
29
+ "react",
30
+ "component"
31
+ ],
32
+ "author": "",
33
+ "license": "MIT",
34
+ "peerDependencies": {
35
+ "@mui/material": "^6.0.0",
36
+ "framer-motion": "^11.0.0",
37
+ "react": "^18.0.0 || ^19.0.0",
38
+ "react-dom": "^18.0.0 || ^19.0.0"
39
+ },
40
+ "devDependencies": {
41
+ "@types/react": "^19.0.1",
42
+ "@types/react-dom": "^19.0.1",
43
+ "@vitejs/plugin-react": "^4.3.4",
44
+ "typescript": "^5.9.3",
45
+ "vite": "^7.2.4"
46
+ }
47
+ }