@moraby/app-launcher 2.0.13 → 2.0.17

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 CHANGED
@@ -137,47 +137,41 @@ function Header() {
137
137
  }
138
138
  ```
139
139
 
140
- ### With Settings UI (Admin Mode)
140
+ ### With Settings UI (Custom User Apps)
141
141
 
142
- The package includes a built-in Settings modal for managing apps.
142
+ The `AppLauncher` can now intelligently handle custom user applications and automatically merge them with your default configuration. Simply add the `allowCustomApps` prop along with a `storageKey`:
143
143
 
144
144
  ```tsx
145
- import { useState } from 'react';
146
- import { AppLauncher, AppSettings, AppItem } from '@moraby/app-launcher';
145
+ import { AppLauncher } from '@moraby/app-launcher';
147
146
  import '@moraby/app-launcher/styles.css';
148
147
 
149
- function AdminLauncher() {
150
- const [showSettings, setShowSettings] = useState(false);
151
- // Your state management logic here (or use provided props)
152
- const [apps, setApps] = useState<AppItem[]>([]);
153
-
148
+ function Header() {
154
149
  return (
155
- <>
156
- {/*
157
- IMPORTANT: 'renderFooter' is required to show the Settings button!
158
- Without it, the launcher will just show the apps list (which might be empty).
159
- */}
150
+ <header>
160
151
  <AppLauncher
161
- apps={apps}
162
- renderFooter={() => <button onClick={() => setShowSettings(true)}>Settings</button>}
163
- />
164
-
165
- <AppSettings
166
- isOpen={showSettings}
167
- onClose={() => setShowSettings(false)}
168
- apps={apps}
169
- onAdd={(app) => setApps([...apps, { ...app, id: Date.now().toString() }])}
170
- onUpdate={(id, updates) =>
171
- setApps(apps.map((a) => (a.id === id ? { ...a, ...updates } : a)))
172
- }
173
- onDelete={(id) => setApps(apps.filter((a) => a.id !== id))}
152
+ configUrl="https://example.com/apps.json"
153
+ storageKey="my-user-apps-storage-key"
154
+ allowCustomApps={true}
174
155
  />
175
- </>
156
+ </header>
176
157
  );
177
158
  }
178
159
  ```
179
160
 
180
- **Note:** If you forget `renderFooter`, there will be no button to open the settings!
161
+ This setup will automatically:
162
+ 1. Fetch default applications from `configUrl`.
163
+ 2. Inject a "Settings" button in the App Launcher dropdown footer.
164
+ 3. Show the built-in Settings modal allowing users to intuitively add, edit, export, and delete custom apps.
165
+ 4. Merge default apps with user-defined apps intrinsically.
166
+ 5. Persist the user's custom preferences safely in `localStorage` securely!
167
+
168
+ ### Modal Rendering & CSS Isolation
169
+
170
+ The `AppSettings` modal renders using a **React Portal** directly attached to `document.body`.
171
+
172
+ - **Placement & Clipping:** This prevents the modal from being clipped by host application styles such as `overflow: hidden` or complex `z-index` stacking contexts.
173
+ - **Client-Side Only:** In Next.js App Router, ensure the component (or its parent wrapper) is a Client Component (`'use client'`) since `document.body` is required.
174
+ - **CSS Isolation:** The launcher utilizes targeted CSS resets (`all: revert`, explicit `box-sizing`) to protect its buttons and SVG icons from host application global styles (e.g., global `button {}` or `svg {}` styles bleeding into the component).
181
175
 
182
176
  ## Configuration JSON Format
183
177
 
@@ -202,12 +196,15 @@ Export your configuration from the admin app and host it as a JSON file:
202
196
 
203
197
  ## Props
204
198
 
205
- | Prop | Type | Description |
206
- | ------------ | ------------------------ | --------------------------------------------- |
207
- | `configUrl` | `string` | URL to fetch configuration from (JSON or API) |
208
- | `apps` | `AppItem[]` | Direct array of apps to display |
209
- | `className` | `string` | Custom class name for the container |
210
- | `onAppClick` | `(app: AppItem) => void` | Custom click handler |
199
+ | Prop | Type | Description |
200
+ | ------------------ | ------------------------ | ------------------------------------------------------------------ |
201
+ | `configUrl` | `string` | URL to fetch default configuration from (JSON or API) |
202
+ | `apps` | `AppItem[]` | Direct array of default apps to display |
203
+ | `className` | `string` | Custom class name for the container |
204
+ | `onAppClick` | `(app: AppItem) => void` | Custom click handler |
205
+ | `storageKey` | `string` | Optional localStorage key to save custom apps alongside defaults |
206
+ | `allowCustomApps` | `boolean` | If true, intrinsically shows the Settings UI to manage user apps |
207
+ | `renderFooter` | `() => ReactNode` | Optional explicitly rendered footer inside the dropdown |
211
208
 
212
209
  ## Icons
213
210