@moraby/app-launcher 0.1.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,117 @@
1
+ # @moraby/app-launcher
2
+
3
+ A Google-style app launcher component for React/Next.js applications.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @moraby/app-launcher
9
+ # or
10
+ yarn add @moraby/app-launcher
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ### With Configuration URL
16
+
17
+ ```tsx
18
+ import { AppLauncher } from '@moraby/app-launcher';
19
+ import '@moraby/app-launcher/styles.css';
20
+
21
+ function Header() {
22
+ return (
23
+ <header>
24
+ <h1>My App</h1>
25
+ <AppLauncher configUrl="https://example.com/apps.json" />
26
+ </header>
27
+ );
28
+ }
29
+ ```
30
+
31
+ ### With Direct Apps Array
32
+
33
+ ```tsx
34
+ import { AppLauncher, AppItem } from '@moraby/app-launcher';
35
+ import '@moraby/app-launcher/styles.css';
36
+
37
+ const apps: AppItem[] = [
38
+ {
39
+ id: 'dashboard',
40
+ name: 'Dashboard',
41
+ url: '/dashboard',
42
+ icon: 'MdDashboard',
43
+ color: '#4285F4',
44
+ },
45
+ {
46
+ id: 'settings',
47
+ name: 'Settings',
48
+ url: '/settings',
49
+ icon: 'FaCog',
50
+ color: '#5f6368',
51
+ },
52
+ ];
53
+
54
+ function Header() {
55
+ return (
56
+ <header>
57
+ <AppLauncher apps={apps} />
58
+ </header>
59
+ );
60
+ }
61
+ ```
62
+
63
+ ## Configuration JSON Format
64
+
65
+ Export your configuration from the admin app and host it as a JSON file:
66
+
67
+ ```json
68
+ {
69
+ "version": "1.0",
70
+ "exportedAt": "2024-01-15T10:00:00.000Z",
71
+ "apps": [
72
+ {
73
+ "id": "my-app",
74
+ "name": "My App",
75
+ "url": "https://myapp.example.com",
76
+ "icon": "FaRocket",
77
+ "color": "#4285F4",
78
+ "description": "My awesome app"
79
+ }
80
+ ]
81
+ }
82
+ ```
83
+
84
+ ## Props
85
+
86
+ | Prop | Type | Description |
87
+ | ------------ | ------------------------ | --------------------------------------------- |
88
+ | `configUrl` | `string` | URL to fetch configuration from (JSON or API) |
89
+ | `apps` | `AppItem[]` | Direct array of apps to display |
90
+ | `className` | `string` | Custom class name for the container |
91
+ | `onAppClick` | `(app: AppItem) => void` | Custom click handler |
92
+
93
+ ## Available Icons
94
+
95
+ The package includes 50+ icons from react-icons. Use any of these names:
96
+
97
+ **Business:** FaBriefcase, IoBusinessSharp, MdWork, FaGraduationCap
98
+
99
+ **Security:** MdOutlineSecurity, FaLock, FaKey, AiOutlineSecurityScan
100
+
101
+ **Communication:** FaEnvelope, MdEmail, FaBell
102
+
103
+ **Media:** FaYoutube, FaMusic, FaCamera, FaImage, FaGamepad
104
+
105
+ **Productivity:** FaCalendarAlt, FaClipboard, FaCalculator, FaFolder, FaFile, FaBookmark, FaTable, FaNewspaper
106
+
107
+ **Navigation:** FaMapMarkerAlt, FaGlobe, FaHome
108
+
109
+ **Development:** FaCode, FaTerminal, FaDatabase, FaPuzzlePiece
110
+
111
+ **Analytics:** FaChartBar, MdDashboard, MdAnalytics
112
+
113
+ **General:** FaRocket, FaUser, FaCog, FaHeart, FaStar, IoApps
114
+
115
+ ## License
116
+
117
+ MIT
package/dist/index.css ADDED
@@ -0,0 +1,147 @@
1
+ /* src/styles.css */
2
+ .app-launcher {
3
+ position: relative;
4
+ display: inline-flex;
5
+ align-items: center;
6
+ }
7
+ .app-launcher__trigger {
8
+ display: flex;
9
+ align-items: center;
10
+ justify-content: center;
11
+ width: 40px;
12
+ height: 40px;
13
+ border: none;
14
+ background: transparent;
15
+ border-radius: 50%;
16
+ cursor: pointer;
17
+ transition: background-color 0.2s ease;
18
+ }
19
+ .app-launcher__trigger:hover {
20
+ background-color: rgba(0, 0, 0, 0.08);
21
+ }
22
+ .app-launcher__trigger:focus {
23
+ outline: none;
24
+ background-color: rgba(0, 0, 0, 0.12);
25
+ }
26
+ .app-launcher__trigger-icon {
27
+ font-size: 24px;
28
+ color: #5f6368;
29
+ }
30
+ .app-launcher__dropdown {
31
+ position: absolute;
32
+ top: calc(100% + 8px);
33
+ right: 0;
34
+ width: 336px;
35
+ max-height: 70vh;
36
+ overflow-y: auto;
37
+ background-color: #ffffff;
38
+ border-radius: 8px;
39
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1), 0 8px 40px rgba(0, 0, 0, 0.2);
40
+ z-index: 9999;
41
+ animation: app-launcher-slide-in 0.15s ease-out;
42
+ }
43
+ @keyframes app-launcher-slide-in {
44
+ from {
45
+ opacity: 0;
46
+ transform: translateY(-8px) scale(0.98);
47
+ }
48
+ to {
49
+ opacity: 1;
50
+ transform: translateY(0) scale(1);
51
+ }
52
+ }
53
+ .app-launcher__grid {
54
+ display: grid;
55
+ grid-template-columns: repeat(3, 1fr);
56
+ gap: 4px;
57
+ padding: 16px 8px;
58
+ }
59
+ .app-launcher__item {
60
+ display: flex;
61
+ flex-direction: column;
62
+ align-items: center;
63
+ justify-content: center;
64
+ padding: 12px 8px;
65
+ border: none;
66
+ background: transparent;
67
+ border-radius: 8px;
68
+ cursor: pointer;
69
+ transition: background-color 0.15s ease;
70
+ min-height: 90px;
71
+ }
72
+ .app-launcher__item:hover {
73
+ background-color: rgba(0, 0, 0, 0.04);
74
+ }
75
+ .app-launcher__item:focus {
76
+ outline: none;
77
+ background-color: rgba(0, 0, 0, 0.08);
78
+ }
79
+ .app-launcher__icon-wrapper {
80
+ display: flex;
81
+ align-items: center;
82
+ justify-content: center;
83
+ width: 48px;
84
+ height: 48px;
85
+ margin-bottom: 8px;
86
+ }
87
+ .app-launcher__icon {
88
+ font-size: 32px;
89
+ transition: transform 0.15s ease;
90
+ }
91
+ .app-launcher__item:hover .app-launcher__icon {
92
+ transform: scale(1.1);
93
+ }
94
+ .app-launcher__name {
95
+ font-family:
96
+ "Google Sans",
97
+ "Roboto",
98
+ -apple-system,
99
+ BlinkMacSystemFont,
100
+ sans-serif;
101
+ font-size: 13px;
102
+ font-weight: 400;
103
+ color: #3c4043;
104
+ text-align: center;
105
+ line-height: 1.3;
106
+ max-width: 100%;
107
+ overflow: hidden;
108
+ text-overflow: ellipsis;
109
+ white-space: nowrap;
110
+ }
111
+ .app-launcher__loading,
112
+ .app-launcher__error {
113
+ padding: 24px;
114
+ text-align: center;
115
+ font-size: 14px;
116
+ color: #5f6368;
117
+ }
118
+ .app-launcher__error {
119
+ color: #d93025;
120
+ }
121
+ .app-launcher__dropdown::-webkit-scrollbar {
122
+ width: 8px;
123
+ }
124
+ .app-launcher__dropdown::-webkit-scrollbar-track {
125
+ background: transparent;
126
+ }
127
+ .app-launcher__dropdown::-webkit-scrollbar-thumb {
128
+ background-color: #dadce0;
129
+ border-radius: 4px;
130
+ }
131
+ @media (max-width: 400px) {
132
+ .app-launcher__dropdown {
133
+ width: 280px;
134
+ right: -8px;
135
+ }
136
+ .app-launcher__icon-wrapper {
137
+ width: 40px;
138
+ height: 40px;
139
+ }
140
+ .app-launcher__icon {
141
+ font-size: 28px;
142
+ }
143
+ .app-launcher__name {
144
+ font-size: 12px;
145
+ }
146
+ }
147
+ /*# sourceMappingURL=index.css.map */
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/styles.css"],"sourcesContent":["/* App Launcher Styles */\r\n\r\n.app-launcher {\r\n position: relative;\r\n display: inline-flex;\r\n align-items: center;\r\n}\r\n\r\n/* Trigger Button */\r\n.app-launcher__trigger {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 40px;\r\n height: 40px;\r\n border: none;\r\n background: transparent;\r\n border-radius: 50%;\r\n cursor: pointer;\r\n transition: background-color 0.2s ease;\r\n}\r\n\r\n.app-launcher__trigger:hover {\r\n background-color: rgba(0, 0, 0, 0.08);\r\n}\r\n\r\n.app-launcher__trigger:focus {\r\n outline: none;\r\n background-color: rgba(0, 0, 0, 0.12);\r\n}\r\n\r\n.app-launcher__trigger-icon {\r\n font-size: 24px;\r\n color: #5f6368;\r\n}\r\n\r\n/* Dropdown */\r\n.app-launcher__dropdown {\r\n position: absolute;\r\n top: calc(100% + 8px);\r\n right: 0;\r\n width: 336px;\r\n max-height: 70vh;\r\n overflow-y: auto;\r\n background-color: #ffffff;\r\n border-radius: 8px;\r\n box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1), 0 8px 40px rgba(0, 0, 0, 0.2);\r\n z-index: 9999;\r\n animation: app-launcher-slide-in 0.15s ease-out;\r\n}\r\n\r\n@keyframes app-launcher-slide-in {\r\n from {\r\n opacity: 0;\r\n transform: translateY(-8px) scale(0.98);\r\n }\r\n to {\r\n opacity: 1;\r\n transform: translateY(0) scale(1);\r\n }\r\n}\r\n\r\n/* Grid */\r\n.app-launcher__grid {\r\n display: grid;\r\n grid-template-columns: repeat(3, 1fr);\r\n gap: 4px;\r\n padding: 16px 8px;\r\n}\r\n\r\n/* Item */\r\n.app-launcher__item {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 12px 8px;\r\n border: none;\r\n background: transparent;\r\n border-radius: 8px;\r\n cursor: pointer;\r\n transition: background-color 0.15s ease;\r\n min-height: 90px;\r\n}\r\n\r\n.app-launcher__item:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n}\r\n\r\n.app-launcher__item:focus {\r\n outline: none;\r\n background-color: rgba(0, 0, 0, 0.08);\r\n}\r\n\r\n/* Icon */\r\n.app-launcher__icon-wrapper {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 48px;\r\n height: 48px;\r\n margin-bottom: 8px;\r\n}\r\n\r\n.app-launcher__icon {\r\n font-size: 32px;\r\n transition: transform 0.15s ease;\r\n}\r\n\r\n.app-launcher__item:hover .app-launcher__icon {\r\n transform: scale(1.1);\r\n}\r\n\r\n/* Name */\r\n.app-launcher__name {\r\n font-family: 'Google Sans', 'Roboto', -apple-system, BlinkMacSystemFont, sans-serif;\r\n font-size: 13px;\r\n font-weight: 400;\r\n color: #3c4043;\r\n text-align: center;\r\n line-height: 1.3;\r\n max-width: 100%;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n}\r\n\r\n/* Loading & Error */\r\n.app-launcher__loading,\r\n.app-launcher__error {\r\n padding: 24px;\r\n text-align: center;\r\n font-size: 14px;\r\n color: #5f6368;\r\n}\r\n\r\n.app-launcher__error {\r\n color: #d93025;\r\n}\r\n\r\n/* Scrollbar */\r\n.app-launcher__dropdown::-webkit-scrollbar {\r\n width: 8px;\r\n}\r\n\r\n.app-launcher__dropdown::-webkit-scrollbar-track {\r\n background: transparent;\r\n}\r\n\r\n.app-launcher__dropdown::-webkit-scrollbar-thumb {\r\n background-color: #dadce0;\r\n border-radius: 4px;\r\n}\r\n\r\n/* Responsive */\r\n@media (max-width: 400px) {\r\n .app-launcher__dropdown {\r\n width: 280px;\r\n right: -8px;\r\n }\r\n\r\n .app-launcher__icon-wrapper {\r\n width: 40px;\r\n height: 40px;\r\n }\r\n\r\n .app-launcher__icon {\r\n font-size: 28px;\r\n }\r\n\r\n .app-launcher__name {\r\n font-size: 12px;\r\n }\r\n}\r\n"],"mappings":";AAEA,CAAC;AACC,YAAU;AACV,WAAS;AACT,eAAa;AACf;AAGA,CAAC;AACC,WAAS;AACT,eAAa;AACb,mBAAiB;AACjB,SAAO;AACP,UAAQ;AACR,UAAQ;AACR,cAAY;AACZ,iBAAe;AACf,UAAQ;AACR,cAAY,iBAAiB,KAAK;AACpC;AAEA,CAbC,qBAaqB;AACpB,oBAAkB,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;AAClC;AAEA,CAjBC,qBAiBqB;AACpB,WAAS;AACT,oBAAkB,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;AAClC;AAEA,CAAC;AACC,aAAW;AACX,SAAO;AACT;AAGA,CAAC;AACC,YAAU;AACV,OAAK,KAAK,KAAK,EAAE;AACjB,SAAO;AACP,SAAO;AACP,cAAY;AACZ,cAAY;AACZ,oBAAkB;AAClB,iBAAe;AACf,cAAY,EAAE,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;AACpE,WAAS;AACT,aAAW,sBAAsB,MAAM;AACzC;AAEA,WAHa;AAIX;AACE,aAAS;AACT,eAAW,WAAW,MAAM,MAAM;AACpC;AACA;AACE,aAAS;AACT,eAAW,WAAW,GAAG,MAAM;AACjC;AACF;AAGA,CAAC;AACC,WAAS;AACT,yBAAuB,OAAO,CAAC,EAAE;AACjC,OAAK;AACL,WAAS,KAAK;AAChB;AAGA,CAAC;AACC,WAAS;AACT,kBAAgB;AAChB,eAAa;AACb,mBAAiB;AACjB,WAAS,KAAK;AACd,UAAQ;AACR,cAAY;AACZ,iBAAe;AACf,UAAQ;AACR,cAAY,iBAAiB,MAAM;AACnC,cAAY;AACd;AAEA,CAdC,kBAckB;AACjB,oBAAkB,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;AAClC;AAEA,CAlBC,kBAkBkB;AACjB,WAAS;AACT,oBAAkB,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;AAClC;AAGA,CAAC;AACC,WAAS;AACT,eAAa;AACb,mBAAiB;AACjB,SAAO;AACP,UAAQ;AACR,iBAAe;AACjB;AAEA,CAAC;AACC,aAAW;AACX,cAAY,UAAU,MAAM;AAC9B;AAEA,CAtCC,kBAsCkB,OAAO,CALzB;AAMC,aAAW,MAAM;AACnB;AAGA,CAAC;AACC;AAAA,IAAa,aAAa;AAAA,IAAE,QAAQ;AAAA,IAAE,aAAa;AAAA,IAAE,kBAAkB;AAAA,IAAE;AACzE,aAAW;AACX,eAAa;AACb,SAAO;AACP,cAAY;AACZ,eAAa;AACb,aAAW;AACX,YAAU;AACV,iBAAe;AACf,eAAa;AACf;AAGA,CAAC;AACD,CAAC;AACC,WAAS;AACT,cAAY;AACZ,aAAW;AACX,SAAO;AACT;AAEA,CAPC;AAQC,SAAO;AACT;AAGA,CAxGC,sBAwGsB;AACrB,SAAO;AACT;AAEA,CA5GC,sBA4GsB;AACrB,cAAY;AACd;AAEA,CAhHC,sBAgHsB;AACrB,oBAAkB;AAClB,iBAAe;AACjB;AAGA,QAAO,WAAY;AACjB,GAvHD;AAwHG,WAAO;AACP,WAAO;AACT;AAEA,GAlED;AAmEG,WAAO;AACP,YAAQ;AACV;AAEA,GA9DD;AA+DG,eAAW;AACb;AAEA,GAxDD;AAyDG,eAAW;AACb;AACF;","names":[]}
@@ -0,0 +1,80 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { IconType } from 'react-icons';
3
+
4
+ /**
5
+ * App configuration for the launcher
6
+ */
7
+ interface AppItem {
8
+ id: string;
9
+ name: string;
10
+ url: string;
11
+ icon: string;
12
+ color: string;
13
+ description?: string;
14
+ }
15
+ /**
16
+ * Configuration object format (from JSON file or API)
17
+ */
18
+ interface AppLauncherConfig {
19
+ version?: string;
20
+ exportedAt?: string;
21
+ apps: AppItem[];
22
+ }
23
+ /**
24
+ * Props for the AppLauncher component
25
+ */
26
+ interface AppLauncherProps {
27
+ /**
28
+ * URL to fetch the configuration from (JSON file or API endpoint)
29
+ * Either configUrl or apps must be provided
30
+ */
31
+ configUrl?: string;
32
+ /**
33
+ * Direct array of apps to display
34
+ * Either configUrl or apps must be provided
35
+ */
36
+ apps?: AppItem[];
37
+ /**
38
+ * Custom class name for the container
39
+ */
40
+ className?: string;
41
+ /**
42
+ * Called when an app is clicked
43
+ */
44
+ onAppClick?: (app: AppItem) => void;
45
+ }
46
+ /**
47
+ * Internal app representation with resolved icon
48
+ */
49
+ interface ResolvedApp {
50
+ id: string;
51
+ name: string;
52
+ url: string;
53
+ icon: IconType;
54
+ color: string;
55
+ description?: string;
56
+ }
57
+
58
+ /**
59
+ * A Google-style app launcher component
60
+ *
61
+ * @example
62
+ * // With config URL
63
+ * <AppLauncher configUrl="https://example.com/apps.json" />
64
+ *
65
+ * @example
66
+ * // With direct apps array
67
+ * <AppLauncher apps={[{ id: '1', name: 'App', url: '/app', icon: 'FaRocket', color: '#4285F4' }]} />
68
+ */
69
+ declare function AppLauncher({ configUrl, apps: propApps, className, onAppClick, }: AppLauncherProps): react_jsx_runtime.JSX.Element;
70
+
71
+ /**
72
+ * Map of icon names to icon components
73
+ */
74
+ declare const iconMap: Record<string, IconType>;
75
+ /**
76
+ * Get icon component by name
77
+ */
78
+ declare function getIcon(name: string): IconType;
79
+
80
+ export { type AppItem, AppLauncher, type AppLauncherConfig, type AppLauncherProps, type ResolvedApp, AppLauncher as default, getIcon, iconMap };
@@ -0,0 +1,80 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { IconType } from 'react-icons';
3
+
4
+ /**
5
+ * App configuration for the launcher
6
+ */
7
+ interface AppItem {
8
+ id: string;
9
+ name: string;
10
+ url: string;
11
+ icon: string;
12
+ color: string;
13
+ description?: string;
14
+ }
15
+ /**
16
+ * Configuration object format (from JSON file or API)
17
+ */
18
+ interface AppLauncherConfig {
19
+ version?: string;
20
+ exportedAt?: string;
21
+ apps: AppItem[];
22
+ }
23
+ /**
24
+ * Props for the AppLauncher component
25
+ */
26
+ interface AppLauncherProps {
27
+ /**
28
+ * URL to fetch the configuration from (JSON file or API endpoint)
29
+ * Either configUrl or apps must be provided
30
+ */
31
+ configUrl?: string;
32
+ /**
33
+ * Direct array of apps to display
34
+ * Either configUrl or apps must be provided
35
+ */
36
+ apps?: AppItem[];
37
+ /**
38
+ * Custom class name for the container
39
+ */
40
+ className?: string;
41
+ /**
42
+ * Called when an app is clicked
43
+ */
44
+ onAppClick?: (app: AppItem) => void;
45
+ }
46
+ /**
47
+ * Internal app representation with resolved icon
48
+ */
49
+ interface ResolvedApp {
50
+ id: string;
51
+ name: string;
52
+ url: string;
53
+ icon: IconType;
54
+ color: string;
55
+ description?: string;
56
+ }
57
+
58
+ /**
59
+ * A Google-style app launcher component
60
+ *
61
+ * @example
62
+ * // With config URL
63
+ * <AppLauncher configUrl="https://example.com/apps.json" />
64
+ *
65
+ * @example
66
+ * // With direct apps array
67
+ * <AppLauncher apps={[{ id: '1', name: 'App', url: '/app', icon: 'FaRocket', color: '#4285F4' }]} />
68
+ */
69
+ declare function AppLauncher({ configUrl, apps: propApps, className, onAppClick, }: AppLauncherProps): react_jsx_runtime.JSX.Element;
70
+
71
+ /**
72
+ * Map of icon names to icon components
73
+ */
74
+ declare const iconMap: Record<string, IconType>;
75
+ /**
76
+ * Get icon component by name
77
+ */
78
+ declare function getIcon(name: string): IconType;
79
+
80
+ export { type AppItem, AppLauncher, type AppLauncherConfig, type AppLauncherProps, type ResolvedApp, AppLauncher as default, getIcon, iconMap };
package/dist/index.js ADDED
@@ -0,0 +1,231 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ AppLauncher: () => AppLauncher,
24
+ default: () => AppLauncher,
25
+ getIcon: () => getIcon,
26
+ iconMap: () => iconMap
27
+ });
28
+ module.exports = __toCommonJS(index_exports);
29
+
30
+ // src/AppLauncher.tsx
31
+ var import_react = require("react");
32
+ var import_io52 = require("react-icons/io5");
33
+
34
+ // src/icons.ts
35
+ var import_fa = require("react-icons/fa");
36
+ var import_fa6 = require("react-icons/fa6");
37
+ var import_gr = require("react-icons/gr");
38
+ var import_io5 = require("react-icons/io5");
39
+ var import_md = require("react-icons/md");
40
+ var import_si = require("react-icons/si");
41
+ var import_ai = require("react-icons/ai");
42
+ var iconMap = {
43
+ // Business & Work
44
+ FaBriefcase: import_fa.FaBriefcase,
45
+ IoBusinessSharp: import_io5.IoBusinessSharp,
46
+ MdWork: import_md.MdWork,
47
+ FaGraduationCap: import_fa.FaGraduationCap,
48
+ // Security
49
+ MdOutlineSecurity: import_md.MdOutlineSecurity,
50
+ FaLock: import_fa.FaLock,
51
+ FaKey: import_fa.FaKey,
52
+ AiOutlineSecurityScan: import_ai.AiOutlineSecurityScan,
53
+ // Communication
54
+ FaEnvelope: import_fa.FaEnvelope,
55
+ MdEmail: import_md.MdEmail,
56
+ FaBell: import_fa.FaBell,
57
+ // Media
58
+ FaYoutube: import_fa.FaYoutube,
59
+ FaMusic: import_fa.FaMusic,
60
+ FaCamera: import_fa.FaCamera,
61
+ FaImage: import_fa.FaImage,
62
+ FaGamepad: import_fa.FaGamepad,
63
+ // Productivity
64
+ FaCalendarAlt: import_fa.FaCalendarAlt,
65
+ FaClipboard: import_fa.FaClipboard,
66
+ FaCalculator: import_fa.FaCalculator,
67
+ FaFolder: import_fa.FaFolder,
68
+ FaFile: import_fa.FaFile,
69
+ FaBookmark: import_fa.FaBookmark,
70
+ FaTable: import_fa.FaTable,
71
+ FaNewspaper: import_fa.FaNewspaper,
72
+ // Navigation
73
+ FaMapMarkerAlt: import_fa.FaMapMarkerAlt,
74
+ FaGlobe: import_fa.FaGlobe,
75
+ FaHome: import_fa.FaHome,
76
+ // Google
77
+ FaGoogle: import_fa.FaGoogle,
78
+ SiGoogledrive: import_si.SiGoogledrive,
79
+ SiGooglemeet: import_si.SiGooglemeet,
80
+ // Development
81
+ FaCode: import_fa.FaCode,
82
+ FaTerminal: import_fa.FaTerminal,
83
+ FaDatabase: import_fa.FaDatabase,
84
+ FaPuzzlePiece: import_fa.FaPuzzlePiece,
85
+ // Analytics
86
+ FaChartBar: import_fa.FaChartBar,
87
+ MdDashboard: import_md.MdDashboard,
88
+ MdAnalytics: import_md.MdAnalytics,
89
+ // Shopping
90
+ FaShoppingCart: import_fa.FaShoppingCart,
91
+ FaGift: import_fa.FaGift,
92
+ FaTicketSimple: import_fa6.FaTicketSimple,
93
+ // Travel
94
+ FaPlane: import_fa.FaPlane,
95
+ FaCar: import_fa.FaCar,
96
+ FaBicycle: import_fa.FaBicycle,
97
+ GrDeliver: import_gr.GrDeliver,
98
+ // Food
99
+ FaUtensils: import_fa.FaUtensils,
100
+ FaCoffee: import_fa.FaCoffee,
101
+ // General
102
+ FaRocket: import_fa.FaRocket,
103
+ FaUser: import_fa.FaUser,
104
+ FaCog: import_fa.FaCog,
105
+ FaHeart: import_fa.FaHeart,
106
+ FaStar: import_fa.FaStar,
107
+ IoApps: import_io5.IoApps
108
+ };
109
+ function getIcon(name) {
110
+ return iconMap[name] || import_fa.FaRocket;
111
+ }
112
+
113
+ // src/AppLauncher.tsx
114
+ var import_jsx_runtime = require("react/jsx-runtime");
115
+ function AppLauncher({
116
+ configUrl,
117
+ apps: propApps,
118
+ className,
119
+ onAppClick
120
+ }) {
121
+ const [isOpen, setIsOpen] = (0, import_react.useState)(false);
122
+ const [apps, setApps] = (0, import_react.useState)([]);
123
+ const [loading, setLoading] = (0, import_react.useState)(false);
124
+ const [error, setError] = (0, import_react.useState)(null);
125
+ const containerRef = (0, import_react.useRef)(null);
126
+ (0, import_react.useEffect)(() => {
127
+ if (propApps) {
128
+ setApps(propApps.map(resolveApp));
129
+ return;
130
+ }
131
+ if (configUrl) {
132
+ setLoading(true);
133
+ setError(null);
134
+ fetch(configUrl).then((res) => {
135
+ if (!res.ok) throw new Error(`Failed to fetch: ${res.status}`);
136
+ return res.json();
137
+ }).then((config) => {
138
+ setApps(config.apps.map(resolveApp));
139
+ }).catch((err) => {
140
+ setError(err.message);
141
+ console.error("AppLauncher: Failed to load config", err);
142
+ }).finally(() => setLoading(false));
143
+ }
144
+ }, [configUrl, propApps]);
145
+ (0, import_react.useEffect)(() => {
146
+ function handleClickOutside(event) {
147
+ if (containerRef.current && !containerRef.current.contains(event.target)) {
148
+ setIsOpen(false);
149
+ }
150
+ }
151
+ if (isOpen) {
152
+ document.addEventListener("mousedown", handleClickOutside);
153
+ }
154
+ return () => document.removeEventListener("mousedown", handleClickOutside);
155
+ }, [isOpen]);
156
+ (0, import_react.useEffect)(() => {
157
+ function handleEscape(event) {
158
+ if (event.key === "Escape") setIsOpen(false);
159
+ }
160
+ if (isOpen) {
161
+ document.addEventListener("keydown", handleEscape);
162
+ }
163
+ return () => document.removeEventListener("keydown", handleEscape);
164
+ }, [isOpen]);
165
+ function resolveApp(app) {
166
+ return {
167
+ id: app.id,
168
+ name: app.name,
169
+ url: app.url,
170
+ icon: getIcon(app.icon),
171
+ color: app.color,
172
+ description: app.description
173
+ };
174
+ }
175
+ function handleAppClick(app) {
176
+ if (onAppClick) {
177
+ onAppClick({
178
+ id: app.id,
179
+ name: app.name,
180
+ url: app.url,
181
+ icon: app.icon.name || "FaRocket",
182
+ color: app.color,
183
+ description: app.description
184
+ });
185
+ } else {
186
+ window.location.href = app.url;
187
+ }
188
+ }
189
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: `app-launcher ${className || ""}`, ref: containerRef, children: [
190
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
191
+ "button",
192
+ {
193
+ className: "app-launcher__trigger",
194
+ onClick: () => setIsOpen(!isOpen),
195
+ "aria-label": "Open app launcher",
196
+ "aria-expanded": isOpen,
197
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_io52.IoApps, { className: "app-launcher__trigger-icon" })
198
+ }
199
+ ),
200
+ isOpen && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "app-launcher__dropdown", children: [
201
+ loading && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "app-launcher__loading", children: "Loading..." }),
202
+ error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "app-launcher__error", children: error }),
203
+ !loading && !error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "app-launcher__grid", children: apps.map((app) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
204
+ "button",
205
+ {
206
+ className: "app-launcher__item",
207
+ onClick: () => handleAppClick(app),
208
+ title: app.description || app.name,
209
+ children: [
210
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "app-launcher__icon-wrapper", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
211
+ app.icon,
212
+ {
213
+ className: "app-launcher__icon",
214
+ style: { color: app.color }
215
+ }
216
+ ) }),
217
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "app-launcher__name", children: app.name })
218
+ ]
219
+ },
220
+ app.id
221
+ )) })
222
+ ] })
223
+ ] });
224
+ }
225
+ // Annotate the CommonJS export names for ESM import in node:
226
+ 0 && (module.exports = {
227
+ AppLauncher,
228
+ getIcon,
229
+ iconMap
230
+ });
231
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/AppLauncher.tsx","../src/icons.ts"],"sourcesContent":["// Main component\r\nexport { AppLauncher, AppLauncher as default } from './AppLauncher';\r\n\r\n// Types\r\nexport type { \r\n AppLauncherProps, \r\n AppItem, \r\n AppLauncherConfig,\r\n ResolvedApp,\r\n} from './types';\r\n\r\n// Icons (in case consumers want to use them)\r\nexport { iconMap, getIcon } from './icons';\r\n","'use client';\r\n\r\nimport React, { useState, useRef, useEffect } from 'react';\r\nimport { IoApps } from 'react-icons/io5';\r\nimport {\r\n AppLauncherProps,\r\n AppItem,\r\n ResolvedApp,\r\n AppLauncherConfig,\r\n} from './types';\r\nimport { getIcon } from './icons';\r\nimport './styles.css';\r\n\r\n/**\r\n * A Google-style app launcher component\r\n *\r\n * @example\r\n * // With config URL\r\n * <AppLauncher configUrl=\"https://example.com/apps.json\" />\r\n *\r\n * @example\r\n * // With direct apps array\r\n * <AppLauncher apps={[{ id: '1', name: 'App', url: '/app', icon: 'FaRocket', color: '#4285F4' }]} />\r\n */\r\nexport function AppLauncher({\r\n configUrl,\r\n apps: propApps,\r\n className,\r\n onAppClick,\r\n}: AppLauncherProps) {\r\n const [isOpen, setIsOpen] = useState(false);\r\n const [apps, setApps] = useState<ResolvedApp[]>([]);\r\n const [loading, setLoading] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n const containerRef = useRef<HTMLDivElement>(null);\r\n\r\n // Resolve apps from props or fetch from URL\r\n useEffect(() => {\r\n if (propApps) {\r\n setApps(propApps.map(resolveApp));\r\n return;\r\n }\r\n\r\n if (configUrl) {\r\n setLoading(true);\r\n setError(null);\r\n\r\n fetch(configUrl)\r\n .then((res) => {\r\n if (!res.ok) throw new Error(`Failed to fetch: ${res.status}`);\r\n return res.json();\r\n })\r\n .then((config: AppLauncherConfig) => {\r\n setApps(config.apps.map(resolveApp));\r\n })\r\n .catch((err) => {\r\n setError(err.message);\r\n console.error('AppLauncher: Failed to load config', err);\r\n })\r\n .finally(() => setLoading(false));\r\n }\r\n }, [configUrl, propApps]);\r\n\r\n // Close on click outside\r\n useEffect(() => {\r\n function handleClickOutside(event: MouseEvent) {\r\n if (\r\n containerRef.current &&\r\n !containerRef.current.contains(event.target as Node)\r\n ) {\r\n setIsOpen(false);\r\n }\r\n }\r\n\r\n if (isOpen) {\r\n document.addEventListener('mousedown', handleClickOutside);\r\n }\r\n return () => document.removeEventListener('mousedown', handleClickOutside);\r\n }, [isOpen]);\r\n\r\n // Close on Escape\r\n useEffect(() => {\r\n function handleEscape(event: KeyboardEvent) {\r\n if (event.key === 'Escape') setIsOpen(false);\r\n }\r\n\r\n if (isOpen) {\r\n document.addEventListener('keydown', handleEscape);\r\n }\r\n return () => document.removeEventListener('keydown', handleEscape);\r\n }, [isOpen]);\r\n\r\n function resolveApp(app: AppItem): ResolvedApp {\r\n return {\r\n id: app.id,\r\n name: app.name,\r\n url: app.url,\r\n icon: getIcon(app.icon),\r\n color: app.color,\r\n description: app.description,\r\n };\r\n }\r\n\r\n function handleAppClick(app: ResolvedApp) {\r\n if (onAppClick) {\r\n onAppClick({\r\n id: app.id,\r\n name: app.name,\r\n url: app.url,\r\n icon: app.icon.name || 'FaRocket',\r\n color: app.color,\r\n description: app.description,\r\n });\r\n } else {\r\n window.location.href = app.url;\r\n }\r\n }\r\n\r\n return (\r\n <div className={`app-launcher ${className || ''}`} ref={containerRef}>\r\n {/* Trigger Button */}\r\n <button\r\n className='app-launcher__trigger'\r\n onClick={() => setIsOpen(!isOpen)}\r\n aria-label='Open app launcher'\r\n aria-expanded={isOpen}\r\n >\r\n <IoApps className='app-launcher__trigger-icon' />\r\n </button>\r\n\r\n {/* Dropdown */}\r\n {isOpen && (\r\n <div className='app-launcher__dropdown'>\r\n {loading && <div className='app-launcher__loading'>Loading...</div>}\r\n\r\n {error && <div className='app-launcher__error'>{error}</div>}\r\n\r\n {!loading && !error && (\r\n <div className='app-launcher__grid'>\r\n {apps.map((app) => (\r\n <button\r\n key={app.id}\r\n className='app-launcher__item'\r\n onClick={() => handleAppClick(app)}\r\n title={app.description || app.name}\r\n >\r\n <div className='app-launcher__icon-wrapper'>\r\n <app.icon\r\n className='app-launcher__icon'\r\n style={{ color: app.color }}\r\n />\r\n </div>\r\n <span className='app-launcher__name'>{app.name}</span>\r\n </button>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\nexport default AppLauncher;\r\n","import { IconType } from 'react-icons';\r\n// prettier-ignore\r\nimport {\r\n FaGoogle, FaEnvelope, FaYoutube, FaCalendarAlt, FaMapMarkerAlt,\r\n FaFile, FaBookmark, FaTable, FaNewspaper, FaImage, FaRocket,\r\n FaHome, FaUser, FaCog, FaChartBar, FaShoppingCart, FaDatabase,\r\n FaCode, FaTerminal, FaGlobe, FaLock, FaKey, FaBell, FaHeart,\r\n FaStar, FaFolder, FaClipboard, FaCalculator, FaMusic, FaCamera,\r\n FaGamepad, FaPuzzlePiece, FaBriefcase, FaGraduationCap, FaPlane,\r\n FaCar, FaBicycle, FaUtensils, FaCoffee, FaGift,\r\n} from 'react-icons/fa';\r\nimport { FaTicketSimple } from 'react-icons/fa6';\r\nimport { GrDeliver } from 'react-icons/gr';\r\nimport { IoBusinessSharp, IoApps } from 'react-icons/io5';\r\nimport { MdOutlineSecurity, MdDashboard, MdAnalytics, MdEmail, MdWork } from 'react-icons/md';\r\nimport { SiGoogledrive, SiGooglemeet } from 'react-icons/si';\r\nimport { AiOutlineSecurityScan } from 'react-icons/ai';\r\n\r\n/**\r\n * Map of icon names to icon components\r\n */\r\n// prettier-ignore\r\nexport const iconMap: Record<string, IconType> = {\r\n // Business & Work\r\n FaBriefcase, IoBusinessSharp, MdWork, FaGraduationCap,\r\n // Security\r\n MdOutlineSecurity, FaLock, FaKey, AiOutlineSecurityScan,\r\n // Communication\r\n FaEnvelope, MdEmail, FaBell,\r\n // Media\r\n FaYoutube, FaMusic, FaCamera, FaImage, FaGamepad,\r\n // Productivity\r\n FaCalendarAlt, FaClipboard, FaCalculator, FaFolder, FaFile,\r\n FaBookmark, FaTable, FaNewspaper,\r\n // Navigation\r\n FaMapMarkerAlt, FaGlobe, FaHome,\r\n // Google\r\n FaGoogle, SiGoogledrive, SiGooglemeet,\r\n // Development\r\n FaCode, FaTerminal, FaDatabase, FaPuzzlePiece,\r\n // Analytics\r\n FaChartBar, MdDashboard, MdAnalytics,\r\n // Shopping\r\n FaShoppingCart, FaGift, FaTicketSimple,\r\n // Travel\r\n FaPlane, FaCar, FaBicycle, GrDeliver,\r\n // Food\r\n FaUtensils, FaCoffee,\r\n // General\r\n FaRocket, FaUser, FaCog, FaHeart, FaStar, IoApps,\r\n};\r\n\r\n/**\r\n * Get icon component by name\r\n */\r\nexport function getIcon(name: string): IconType {\r\n return iconMap[name] || FaRocket;\r\n}\r\n"],"mappings":"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","names":["import_io5"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,243 @@
1
+ // src/AppLauncher.tsx
2
+ import { useState, useRef, useEffect } from "react";
3
+ import { IoApps as IoApps2 } from "react-icons/io5";
4
+
5
+ // src/icons.ts
6
+ import {
7
+ FaGoogle,
8
+ FaEnvelope,
9
+ FaYoutube,
10
+ FaCalendarAlt,
11
+ FaMapMarkerAlt,
12
+ FaFile,
13
+ FaBookmark,
14
+ FaTable,
15
+ FaNewspaper,
16
+ FaImage,
17
+ FaRocket,
18
+ FaHome,
19
+ FaUser,
20
+ FaCog,
21
+ FaChartBar,
22
+ FaShoppingCart,
23
+ FaDatabase,
24
+ FaCode,
25
+ FaTerminal,
26
+ FaGlobe,
27
+ FaLock,
28
+ FaKey,
29
+ FaBell,
30
+ FaHeart,
31
+ FaStar,
32
+ FaFolder,
33
+ FaClipboard,
34
+ FaCalculator,
35
+ FaMusic,
36
+ FaCamera,
37
+ FaGamepad,
38
+ FaPuzzlePiece,
39
+ FaBriefcase,
40
+ FaGraduationCap,
41
+ FaPlane,
42
+ FaCar,
43
+ FaBicycle,
44
+ FaUtensils,
45
+ FaCoffee,
46
+ FaGift
47
+ } from "react-icons/fa";
48
+ import { FaTicketSimple } from "react-icons/fa6";
49
+ import { GrDeliver } from "react-icons/gr";
50
+ import { IoBusinessSharp, IoApps } from "react-icons/io5";
51
+ import { MdOutlineSecurity, MdDashboard, MdAnalytics, MdEmail, MdWork } from "react-icons/md";
52
+ import { SiGoogledrive, SiGooglemeet } from "react-icons/si";
53
+ import { AiOutlineSecurityScan } from "react-icons/ai";
54
+ var iconMap = {
55
+ // Business & Work
56
+ FaBriefcase,
57
+ IoBusinessSharp,
58
+ MdWork,
59
+ FaGraduationCap,
60
+ // Security
61
+ MdOutlineSecurity,
62
+ FaLock,
63
+ FaKey,
64
+ AiOutlineSecurityScan,
65
+ // Communication
66
+ FaEnvelope,
67
+ MdEmail,
68
+ FaBell,
69
+ // Media
70
+ FaYoutube,
71
+ FaMusic,
72
+ FaCamera,
73
+ FaImage,
74
+ FaGamepad,
75
+ // Productivity
76
+ FaCalendarAlt,
77
+ FaClipboard,
78
+ FaCalculator,
79
+ FaFolder,
80
+ FaFile,
81
+ FaBookmark,
82
+ FaTable,
83
+ FaNewspaper,
84
+ // Navigation
85
+ FaMapMarkerAlt,
86
+ FaGlobe,
87
+ FaHome,
88
+ // Google
89
+ FaGoogle,
90
+ SiGoogledrive,
91
+ SiGooglemeet,
92
+ // Development
93
+ FaCode,
94
+ FaTerminal,
95
+ FaDatabase,
96
+ FaPuzzlePiece,
97
+ // Analytics
98
+ FaChartBar,
99
+ MdDashboard,
100
+ MdAnalytics,
101
+ // Shopping
102
+ FaShoppingCart,
103
+ FaGift,
104
+ FaTicketSimple,
105
+ // Travel
106
+ FaPlane,
107
+ FaCar,
108
+ FaBicycle,
109
+ GrDeliver,
110
+ // Food
111
+ FaUtensils,
112
+ FaCoffee,
113
+ // General
114
+ FaRocket,
115
+ FaUser,
116
+ FaCog,
117
+ FaHeart,
118
+ FaStar,
119
+ IoApps
120
+ };
121
+ function getIcon(name) {
122
+ return iconMap[name] || FaRocket;
123
+ }
124
+
125
+ // src/AppLauncher.tsx
126
+ import { jsx, jsxs } from "react/jsx-runtime";
127
+ function AppLauncher({
128
+ configUrl,
129
+ apps: propApps,
130
+ className,
131
+ onAppClick
132
+ }) {
133
+ const [isOpen, setIsOpen] = useState(false);
134
+ const [apps, setApps] = useState([]);
135
+ const [loading, setLoading] = useState(false);
136
+ const [error, setError] = useState(null);
137
+ const containerRef = useRef(null);
138
+ useEffect(() => {
139
+ if (propApps) {
140
+ setApps(propApps.map(resolveApp));
141
+ return;
142
+ }
143
+ if (configUrl) {
144
+ setLoading(true);
145
+ setError(null);
146
+ fetch(configUrl).then((res) => {
147
+ if (!res.ok) throw new Error(`Failed to fetch: ${res.status}`);
148
+ return res.json();
149
+ }).then((config) => {
150
+ setApps(config.apps.map(resolveApp));
151
+ }).catch((err) => {
152
+ setError(err.message);
153
+ console.error("AppLauncher: Failed to load config", err);
154
+ }).finally(() => setLoading(false));
155
+ }
156
+ }, [configUrl, propApps]);
157
+ useEffect(() => {
158
+ function handleClickOutside(event) {
159
+ if (containerRef.current && !containerRef.current.contains(event.target)) {
160
+ setIsOpen(false);
161
+ }
162
+ }
163
+ if (isOpen) {
164
+ document.addEventListener("mousedown", handleClickOutside);
165
+ }
166
+ return () => document.removeEventListener("mousedown", handleClickOutside);
167
+ }, [isOpen]);
168
+ useEffect(() => {
169
+ function handleEscape(event) {
170
+ if (event.key === "Escape") setIsOpen(false);
171
+ }
172
+ if (isOpen) {
173
+ document.addEventListener("keydown", handleEscape);
174
+ }
175
+ return () => document.removeEventListener("keydown", handleEscape);
176
+ }, [isOpen]);
177
+ function resolveApp(app) {
178
+ return {
179
+ id: app.id,
180
+ name: app.name,
181
+ url: app.url,
182
+ icon: getIcon(app.icon),
183
+ color: app.color,
184
+ description: app.description
185
+ };
186
+ }
187
+ function handleAppClick(app) {
188
+ if (onAppClick) {
189
+ onAppClick({
190
+ id: app.id,
191
+ name: app.name,
192
+ url: app.url,
193
+ icon: app.icon.name || "FaRocket",
194
+ color: app.color,
195
+ description: app.description
196
+ });
197
+ } else {
198
+ window.location.href = app.url;
199
+ }
200
+ }
201
+ return /* @__PURE__ */ jsxs("div", { className: `app-launcher ${className || ""}`, ref: containerRef, children: [
202
+ /* @__PURE__ */ jsx(
203
+ "button",
204
+ {
205
+ className: "app-launcher__trigger",
206
+ onClick: () => setIsOpen(!isOpen),
207
+ "aria-label": "Open app launcher",
208
+ "aria-expanded": isOpen,
209
+ children: /* @__PURE__ */ jsx(IoApps2, { className: "app-launcher__trigger-icon" })
210
+ }
211
+ ),
212
+ isOpen && /* @__PURE__ */ jsxs("div", { className: "app-launcher__dropdown", children: [
213
+ loading && /* @__PURE__ */ jsx("div", { className: "app-launcher__loading", children: "Loading..." }),
214
+ error && /* @__PURE__ */ jsx("div", { className: "app-launcher__error", children: error }),
215
+ !loading && !error && /* @__PURE__ */ jsx("div", { className: "app-launcher__grid", children: apps.map((app) => /* @__PURE__ */ jsxs(
216
+ "button",
217
+ {
218
+ className: "app-launcher__item",
219
+ onClick: () => handleAppClick(app),
220
+ title: app.description || app.name,
221
+ children: [
222
+ /* @__PURE__ */ jsx("div", { className: "app-launcher__icon-wrapper", children: /* @__PURE__ */ jsx(
223
+ app.icon,
224
+ {
225
+ className: "app-launcher__icon",
226
+ style: { color: app.color }
227
+ }
228
+ ) }),
229
+ /* @__PURE__ */ jsx("span", { className: "app-launcher__name", children: app.name })
230
+ ]
231
+ },
232
+ app.id
233
+ )) })
234
+ ] })
235
+ ] });
236
+ }
237
+ export {
238
+ AppLauncher,
239
+ AppLauncher as default,
240
+ getIcon,
241
+ iconMap
242
+ };
243
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/AppLauncher.tsx","../src/icons.ts"],"sourcesContent":["'use client';\r\n\r\nimport React, { useState, useRef, useEffect } from 'react';\r\nimport { IoApps } from 'react-icons/io5';\r\nimport {\r\n AppLauncherProps,\r\n AppItem,\r\n ResolvedApp,\r\n AppLauncherConfig,\r\n} from './types';\r\nimport { getIcon } from './icons';\r\nimport './styles.css';\r\n\r\n/**\r\n * A Google-style app launcher component\r\n *\r\n * @example\r\n * // With config URL\r\n * <AppLauncher configUrl=\"https://example.com/apps.json\" />\r\n *\r\n * @example\r\n * // With direct apps array\r\n * <AppLauncher apps={[{ id: '1', name: 'App', url: '/app', icon: 'FaRocket', color: '#4285F4' }]} />\r\n */\r\nexport function AppLauncher({\r\n configUrl,\r\n apps: propApps,\r\n className,\r\n onAppClick,\r\n}: AppLauncherProps) {\r\n const [isOpen, setIsOpen] = useState(false);\r\n const [apps, setApps] = useState<ResolvedApp[]>([]);\r\n const [loading, setLoading] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n const containerRef = useRef<HTMLDivElement>(null);\r\n\r\n // Resolve apps from props or fetch from URL\r\n useEffect(() => {\r\n if (propApps) {\r\n setApps(propApps.map(resolveApp));\r\n return;\r\n }\r\n\r\n if (configUrl) {\r\n setLoading(true);\r\n setError(null);\r\n\r\n fetch(configUrl)\r\n .then((res) => {\r\n if (!res.ok) throw new Error(`Failed to fetch: ${res.status}`);\r\n return res.json();\r\n })\r\n .then((config: AppLauncherConfig) => {\r\n setApps(config.apps.map(resolveApp));\r\n })\r\n .catch((err) => {\r\n setError(err.message);\r\n console.error('AppLauncher: Failed to load config', err);\r\n })\r\n .finally(() => setLoading(false));\r\n }\r\n }, [configUrl, propApps]);\r\n\r\n // Close on click outside\r\n useEffect(() => {\r\n function handleClickOutside(event: MouseEvent) {\r\n if (\r\n containerRef.current &&\r\n !containerRef.current.contains(event.target as Node)\r\n ) {\r\n setIsOpen(false);\r\n }\r\n }\r\n\r\n if (isOpen) {\r\n document.addEventListener('mousedown', handleClickOutside);\r\n }\r\n return () => document.removeEventListener('mousedown', handleClickOutside);\r\n }, [isOpen]);\r\n\r\n // Close on Escape\r\n useEffect(() => {\r\n function handleEscape(event: KeyboardEvent) {\r\n if (event.key === 'Escape') setIsOpen(false);\r\n }\r\n\r\n if (isOpen) {\r\n document.addEventListener('keydown', handleEscape);\r\n }\r\n return () => document.removeEventListener('keydown', handleEscape);\r\n }, [isOpen]);\r\n\r\n function resolveApp(app: AppItem): ResolvedApp {\r\n return {\r\n id: app.id,\r\n name: app.name,\r\n url: app.url,\r\n icon: getIcon(app.icon),\r\n color: app.color,\r\n description: app.description,\r\n };\r\n }\r\n\r\n function handleAppClick(app: ResolvedApp) {\r\n if (onAppClick) {\r\n onAppClick({\r\n id: app.id,\r\n name: app.name,\r\n url: app.url,\r\n icon: app.icon.name || 'FaRocket',\r\n color: app.color,\r\n description: app.description,\r\n });\r\n } else {\r\n window.location.href = app.url;\r\n }\r\n }\r\n\r\n return (\r\n <div className={`app-launcher ${className || ''}`} ref={containerRef}>\r\n {/* Trigger Button */}\r\n <button\r\n className='app-launcher__trigger'\r\n onClick={() => setIsOpen(!isOpen)}\r\n aria-label='Open app launcher'\r\n aria-expanded={isOpen}\r\n >\r\n <IoApps className='app-launcher__trigger-icon' />\r\n </button>\r\n\r\n {/* Dropdown */}\r\n {isOpen && (\r\n <div className='app-launcher__dropdown'>\r\n {loading && <div className='app-launcher__loading'>Loading...</div>}\r\n\r\n {error && <div className='app-launcher__error'>{error}</div>}\r\n\r\n {!loading && !error && (\r\n <div className='app-launcher__grid'>\r\n {apps.map((app) => (\r\n <button\r\n key={app.id}\r\n className='app-launcher__item'\r\n onClick={() => handleAppClick(app)}\r\n title={app.description || app.name}\r\n >\r\n <div className='app-launcher__icon-wrapper'>\r\n <app.icon\r\n className='app-launcher__icon'\r\n style={{ color: app.color }}\r\n />\r\n </div>\r\n <span className='app-launcher__name'>{app.name}</span>\r\n </button>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\nexport default AppLauncher;\r\n","import { IconType } from 'react-icons';\r\n// prettier-ignore\r\nimport {\r\n FaGoogle, FaEnvelope, FaYoutube, FaCalendarAlt, FaMapMarkerAlt,\r\n FaFile, FaBookmark, FaTable, FaNewspaper, FaImage, FaRocket,\r\n FaHome, FaUser, FaCog, FaChartBar, FaShoppingCart, FaDatabase,\r\n FaCode, FaTerminal, FaGlobe, FaLock, FaKey, FaBell, FaHeart,\r\n FaStar, FaFolder, FaClipboard, FaCalculator, FaMusic, FaCamera,\r\n FaGamepad, FaPuzzlePiece, FaBriefcase, FaGraduationCap, FaPlane,\r\n FaCar, FaBicycle, FaUtensils, FaCoffee, FaGift,\r\n} from 'react-icons/fa';\r\nimport { FaTicketSimple } from 'react-icons/fa6';\r\nimport { GrDeliver } from 'react-icons/gr';\r\nimport { IoBusinessSharp, IoApps } from 'react-icons/io5';\r\nimport { MdOutlineSecurity, MdDashboard, MdAnalytics, MdEmail, MdWork } from 'react-icons/md';\r\nimport { SiGoogledrive, SiGooglemeet } from 'react-icons/si';\r\nimport { AiOutlineSecurityScan } from 'react-icons/ai';\r\n\r\n/**\r\n * Map of icon names to icon components\r\n */\r\n// prettier-ignore\r\nexport const iconMap: Record<string, IconType> = {\r\n // Business & Work\r\n FaBriefcase, IoBusinessSharp, MdWork, FaGraduationCap,\r\n // Security\r\n MdOutlineSecurity, FaLock, FaKey, AiOutlineSecurityScan,\r\n // Communication\r\n FaEnvelope, MdEmail, FaBell,\r\n // Media\r\n FaYoutube, FaMusic, FaCamera, FaImage, FaGamepad,\r\n // Productivity\r\n FaCalendarAlt, FaClipboard, FaCalculator, FaFolder, FaFile,\r\n FaBookmark, FaTable, FaNewspaper,\r\n // Navigation\r\n FaMapMarkerAlt, FaGlobe, FaHome,\r\n // Google\r\n FaGoogle, SiGoogledrive, SiGooglemeet,\r\n // Development\r\n FaCode, FaTerminal, FaDatabase, FaPuzzlePiece,\r\n // Analytics\r\n FaChartBar, MdDashboard, MdAnalytics,\r\n // Shopping\r\n FaShoppingCart, FaGift, FaTicketSimple,\r\n // Travel\r\n FaPlane, FaCar, FaBicycle, GrDeliver,\r\n // Food\r\n FaUtensils, FaCoffee,\r\n // General\r\n FaRocket, FaUser, FaCog, FaHeart, FaStar, IoApps,\r\n};\r\n\r\n/**\r\n * Get icon component by name\r\n */\r\nexport function getIcon(name: string): IconType {\r\n return iconMap[name] || FaRocket;\r\n}\r\n"],"mappings":"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","names":["IoApps","IoApps"]}
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@moraby/app-launcher",
3
+ "version": "0.1.0",
4
+ "description": "A Google-style app launcher component for React/Next.js applications",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js"
13
+ },
14
+ "./styles.css": "./dist/index.css"
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsup",
21
+ "dev": "tsup --watch",
22
+ "prepublishOnly": "npm run build"
23
+ },
24
+ "peerDependencies": {
25
+ "react": ">=17.0.0",
26
+ "react-dom": ">=17.0.0"
27
+ },
28
+ "dependencies": {
29
+ "react-icons": "^5.0.0"
30
+ },
31
+ "devDependencies": {
32
+ "@types/react": "^18.0.0",
33
+ "@types/react-dom": "^18.0.0",
34
+ "tsup": "^8.0.0",
35
+ "typescript": "^5.0.0"
36
+ },
37
+ "keywords": [
38
+ "react",
39
+ "nextjs",
40
+ "app-launcher",
41
+ "google-apps",
42
+ "launcher",
43
+ "menu",
44
+ "dropdown"
45
+ ],
46
+ "author": "Morteza Araby",
47
+ "license": "MIT",
48
+ "repository": {
49
+ "type": "git",
50
+ "url": "https://github.com/morteza-araby/app-launcher"
51
+ }
52
+ }