ywana-core8 0.2.3 → 0.2.5

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/dist/index.umd.js CHANGED
@@ -32253,6 +32253,386 @@ const rows = [
32253
32253
  statusBar && /* @__PURE__ */ React.createElement("div", { className: "window__status-bar" }, statusBar)
32254
32254
  );
32255
32255
  };
32256
+ const ApplicationMenu = ({ isOpen, onClose }) => {
32257
+ const appManager = useAppManager();
32258
+ const [searchTerm, setSearchTerm] = React.useState("");
32259
+ const [selectedCategory, setSelectedCategory] = React.useState("all");
32260
+ const [apps, setApps] = React.useState([]);
32261
+ const [categories, setCategories] = React.useState([]);
32262
+ const searchInputRef = React.useRef(null);
32263
+ const { createWindow } = useWindows();
32264
+ React.useEffect(() => {
32265
+ const loadData = () => {
32266
+ setApps(appManager.getAllApps());
32267
+ setCategories(appManager.getAllCategories());
32268
+ };
32269
+ loadData();
32270
+ appManager.addListener(loadData);
32271
+ return () => {
32272
+ appManager.removeListener(loadData);
32273
+ };
32274
+ }, [appManager]);
32275
+ React.useEffect(() => {
32276
+ if (isOpen && searchInputRef.current) {
32277
+ setTimeout(() => {
32278
+ searchInputRef.current.focus();
32279
+ }, 100);
32280
+ }
32281
+ }, [isOpen]);
32282
+ React.useEffect(() => {
32283
+ const handleKeyDown = (e) => {
32284
+ if (e.key === "Escape" && isOpen) {
32285
+ onClose();
32286
+ }
32287
+ };
32288
+ if (isOpen) {
32289
+ document.addEventListener("keydown", handleKeyDown);
32290
+ return () => document.removeEventListener("keydown", handleKeyDown);
32291
+ }
32292
+ }, [isOpen, onClose]);
32293
+ const filteredApps = apps.filter((app) => {
32294
+ const matchesSearch = searchTerm === "" || app.name.toLowerCase().includes(searchTerm.toLowerCase()) || app.description.toLowerCase().includes(searchTerm.toLowerCase());
32295
+ const matchesCategory = selectedCategory === "all" || app.category.toLowerCase() === selectedCategory.toLowerCase();
32296
+ return matchesSearch && matchesCategory;
32297
+ });
32298
+ const groupedApps = filteredApps.reduce((groups, app) => {
32299
+ const category = app.category;
32300
+ if (!groups[category]) {
32301
+ groups[category] = [];
32302
+ }
32303
+ groups[category].push(app);
32304
+ return groups;
32305
+ }, {});
32306
+ const handleLaunchApp = (app) => {
32307
+ createWindow({
32308
+ id: `${app.id}-${Date.now()}`,
32309
+ title: app.name,
32310
+ icon: app.icon,
32311
+ size: app.size,
32312
+ toolbar: app.toolbar,
32313
+ statusBar: app.statusBar,
32314
+ content: app.component || /* @__PURE__ */ React.createElement("div", { style: { padding: "20px", textAlign: "center" } }, /* @__PURE__ */ React.createElement("div", { style: { fontSize: "48px", marginBottom: "16px" } }, app.icon), /* @__PURE__ */ React.createElement("h2", null, app.name), /* @__PURE__ */ React.createElement("p", { style: { color: "#666", marginBottom: "20px" } }, app.description), /* @__PURE__ */ React.createElement("p", { style: { fontSize: "14px", color: "#999" } }, "This is a placeholder for the ", app.name, " application."))
32315
+ });
32316
+ onClose();
32317
+ };
32318
+ const handleCategorySelect = (categoryId) => {
32319
+ setSelectedCategory(categoryId);
32320
+ setSearchTerm("");
32321
+ };
32322
+ if (!isOpen) return null;
32323
+ return /* @__PURE__ */ React.createElement("div", { className: "application-menu-overlay", onClick: onClose }, /* @__PURE__ */ React.createElement("div", { className: "application-menu", onClick: (e) => e.stopPropagation() }, /* @__PURE__ */ React.createElement("div", { className: "application-menu__header" }, /* @__PURE__ */ React.createElement("h2", null, "Applications"), /* @__PURE__ */ React.createElement(
32324
+ "button",
32325
+ {
32326
+ className: "application-menu__close",
32327
+ onClick: onClose,
32328
+ title: "Close menu"
32329
+ },
32330
+ "×"
32331
+ )), /* @__PURE__ */ React.createElement("div", { className: "application-menu__search" }, /* @__PURE__ */ React.createElement(
32332
+ "input",
32333
+ {
32334
+ ref: searchInputRef,
32335
+ type: "text",
32336
+ placeholder: "Search applications...",
32337
+ value: searchTerm,
32338
+ onChange: (e) => setSearchTerm(e.target.value),
32339
+ className: "application-menu__search-input"
32340
+ }
32341
+ )), /* @__PURE__ */ React.createElement("div", { className: "application-menu__categories" }, /* @__PURE__ */ React.createElement(
32342
+ "button",
32343
+ {
32344
+ className: `application-menu__category ${selectedCategory === "all" ? "active" : ""}`,
32345
+ onClick: () => handleCategorySelect("all")
32346
+ },
32347
+ /* @__PURE__ */ React.createElement("span", { className: "category-icon" }, "📱"),
32348
+ "All Apps"
32349
+ ), categories.map((category) => /* @__PURE__ */ React.createElement(
32350
+ "button",
32351
+ {
32352
+ key: category.id,
32353
+ className: `application-menu__category ${selectedCategory === category.id ? "active" : ""}`,
32354
+ onClick: () => handleCategorySelect(category.id)
32355
+ },
32356
+ /* @__PURE__ */ React.createElement("span", { className: "category-icon" }, category.icon),
32357
+ category.name
32358
+ ))), /* @__PURE__ */ React.createElement("div", { className: "application-menu__content" }, searchTerm && /* @__PURE__ */ React.createElement("div", { className: "application-menu__search-results" }, /* @__PURE__ */ React.createElement("h3", null, "Search Results (", filteredApps.length, ")"), /* @__PURE__ */ React.createElement("div", { className: "application-menu__apps-grid" }, filteredApps.map((app) => /* @__PURE__ */ React.createElement(
32359
+ "div",
32360
+ {
32361
+ key: app.id,
32362
+ className: "application-menu__app",
32363
+ onClick: () => handleLaunchApp(app),
32364
+ title: app.description
32365
+ },
32366
+ /* @__PURE__ */ React.createElement("div", { className: "app-icon" }, app.icon),
32367
+ /* @__PURE__ */ React.createElement("div", { className: "app-name" }, app.name)
32368
+ )))), !searchTerm && /* @__PURE__ */ React.createElement("div", { className: "application-menu__categories-content" }, Object.entries(groupedApps).map(([categoryName, categoryApps]) => /* @__PURE__ */ React.createElement("div", { key: categoryName, className: "application-menu__category-section" }, /* @__PURE__ */ React.createElement("h3", { className: "category-title" }, categoryName), /* @__PURE__ */ React.createElement("div", { className: "application-menu__apps-grid" }, categoryApps.map((app) => /* @__PURE__ */ React.createElement(
32369
+ "div",
32370
+ {
32371
+ key: app.id,
32372
+ className: "application-menu__app",
32373
+ onClick: () => handleLaunchApp(app),
32374
+ title: app.description
32375
+ },
32376
+ /* @__PURE__ */ React.createElement("div", { className: "app-icon" }, app.icon),
32377
+ /* @__PURE__ */ React.createElement("div", { className: "app-name" }, app.name)
32378
+ )))))), filteredApps.length === 0 && /* @__PURE__ */ React.createElement("div", { className: "application-menu__no-results" }, /* @__PURE__ */ React.createElement("div", { style: { fontSize: "48px", marginBottom: "16px" } }, "🔍"), /* @__PURE__ */ React.createElement("h3", null, "No applications found"), /* @__PURE__ */ React.createElement("p", null, "Try adjusting your search or category filter.")))));
32379
+ };
32380
+ class AppManager {
32381
+ constructor() {
32382
+ this.applications = /* @__PURE__ */ new Map();
32383
+ this.categories = /* @__PURE__ */ new Map();
32384
+ this.listeners = /* @__PURE__ */ new Set();
32385
+ this.initializeDefaultApps();
32386
+ }
32387
+ /**
32388
+ * Initialize default applications
32389
+ */
32390
+ initializeDefaultApps() {
32391
+ this.registerApp({
32392
+ id: "file-explorer",
32393
+ name: "File Explorer",
32394
+ description: "Browse and manage files",
32395
+ icon: "📁",
32396
+ category: "System",
32397
+ component: null,
32398
+ // Will be set when registering actual components
32399
+ size: { width: 600, height: 400 },
32400
+ toolbar: null,
32401
+ statusBar: null
32402
+ });
32403
+ this.registerApp({
32404
+ id: "text-editor",
32405
+ name: "Text Editor",
32406
+ description: "Edit text files",
32407
+ icon: "📝",
32408
+ category: "Productivity",
32409
+ component: null,
32410
+ size: { width: 500, height: 350 },
32411
+ toolbar: null,
32412
+ statusBar: null
32413
+ });
32414
+ this.registerApp({
32415
+ id: "calculator",
32416
+ name: "Calculator",
32417
+ description: "Perform calculations",
32418
+ icon: "🧮",
32419
+ category: "Utilities",
32420
+ component: null,
32421
+ size: { width: 300, height: 400 }
32422
+ });
32423
+ this.registerApp({
32424
+ id: "settings",
32425
+ name: "Settings",
32426
+ description: "System configuration",
32427
+ icon: "⚙️",
32428
+ category: "System",
32429
+ component: null,
32430
+ size: { width: 450, height: 300 }
32431
+ });
32432
+ this.registerApp({
32433
+ id: "browser",
32434
+ name: "Web Browser",
32435
+ description: "Browse the internet",
32436
+ icon: "🌐",
32437
+ category: "Internet",
32438
+ component: null,
32439
+ size: { width: 800, height: 500 }
32440
+ });
32441
+ this.registerApp({
32442
+ id: "terminal",
32443
+ name: "Terminal",
32444
+ description: "Command line interface",
32445
+ icon: "💻",
32446
+ category: "Development",
32447
+ component: null,
32448
+ size: { width: 700, height: 400 }
32449
+ });
32450
+ this.registerApp({
32451
+ id: "image-viewer",
32452
+ name: "Image Viewer",
32453
+ description: "View and edit images",
32454
+ icon: "🖼️",
32455
+ category: "Media",
32456
+ component: null,
32457
+ size: { width: 600, height: 500 }
32458
+ });
32459
+ this.registerApp({
32460
+ id: "music-player",
32461
+ name: "Music Player",
32462
+ description: "Play audio files",
32463
+ icon: "🎵",
32464
+ category: "Media",
32465
+ component: null,
32466
+ size: { width: 400, height: 300 }
32467
+ });
32468
+ this.initializeCategories();
32469
+ }
32470
+ /**
32471
+ * Initialize application categories
32472
+ */
32473
+ initializeCategories() {
32474
+ const categoryData = [
32475
+ { id: "system", name: "System", icon: "⚙️", color: "#607d8b" },
32476
+ { id: "productivity", name: "Productivity", icon: "📊", color: "#2196f3" },
32477
+ { id: "utilities", name: "Utilities", icon: "🔧", color: "#ff9800" },
32478
+ { id: "internet", name: "Internet", icon: "🌐", color: "#4caf50" },
32479
+ { id: "development", name: "Development", icon: "💻", color: "#9c27b0" },
32480
+ { id: "media", name: "Media", icon: "🎬", color: "#e91e63" },
32481
+ { id: "games", name: "Games", icon: "🎮", color: "#f44336" }
32482
+ ];
32483
+ categoryData.forEach((category) => {
32484
+ this.categories.set(category.id, category);
32485
+ });
32486
+ }
32487
+ /**
32488
+ * Register a new application
32489
+ */
32490
+ registerApp(appConfig) {
32491
+ const app = {
32492
+ id: appConfig.id,
32493
+ name: appConfig.name,
32494
+ description: appConfig.description || "",
32495
+ icon: appConfig.icon || "📄",
32496
+ category: appConfig.category || "Utilities",
32497
+ component: appConfig.component || null,
32498
+ size: appConfig.size || { width: 600, height: 400 },
32499
+ toolbar: appConfig.toolbar || null,
32500
+ statusBar: appConfig.statusBar || null,
32501
+ ...appConfig
32502
+ };
32503
+ this.applications.set(app.id, app);
32504
+ this.notifyListeners();
32505
+ return app.id;
32506
+ }
32507
+ /**
32508
+ * Unregister an application
32509
+ */
32510
+ unregisterApp(appId) {
32511
+ const removed = this.applications.delete(appId);
32512
+ if (removed) {
32513
+ this.notifyListeners();
32514
+ }
32515
+ return removed;
32516
+ }
32517
+ /**
32518
+ * Get an application by ID
32519
+ */
32520
+ getApp(appId) {
32521
+ return this.applications.get(appId);
32522
+ }
32523
+ /**
32524
+ * Get all applications
32525
+ */
32526
+ getAllApps() {
32527
+ return Array.from(this.applications.values());
32528
+ }
32529
+ /**
32530
+ * Get applications by category
32531
+ */
32532
+ getAppsByCategory(categoryId) {
32533
+ return Array.from(this.applications.values()).filter((app) => app.category.toLowerCase() === categoryId.toLowerCase());
32534
+ }
32535
+ /**
32536
+ * Get all categories
32537
+ */
32538
+ getAllCategories() {
32539
+ return Array.from(this.categories.values());
32540
+ }
32541
+ /**
32542
+ * Get category by ID
32543
+ */
32544
+ getCategory(categoryId) {
32545
+ return this.categories.get(categoryId.toLowerCase());
32546
+ }
32547
+ /**
32548
+ * Search applications
32549
+ */
32550
+ searchApps(query) {
32551
+ const searchTerm = query.toLowerCase();
32552
+ return Array.from(this.applications.values()).filter(
32553
+ (app) => app.name.toLowerCase().includes(searchTerm) || app.description.toLowerCase().includes(searchTerm) || app.category.toLowerCase().includes(searchTerm)
32554
+ );
32555
+ }
32556
+ /**
32557
+ * Add listener for changes
32558
+ */
32559
+ addListener(listener) {
32560
+ this.listeners.add(listener);
32561
+ }
32562
+ /**
32563
+ * Remove listener
32564
+ */
32565
+ removeListener(listener) {
32566
+ this.listeners.delete(listener);
32567
+ }
32568
+ /**
32569
+ * Notify all listeners about changes
32570
+ */
32571
+ notifyListeners() {
32572
+ this.listeners.forEach((listener) => listener(this.getAllApps()));
32573
+ }
32574
+ /**
32575
+ * Get applications grouped by category
32576
+ */
32577
+ getAppsGroupedByCategory() {
32578
+ const grouped = {};
32579
+ const categories = this.getAllCategories();
32580
+ categories.forEach((category) => {
32581
+ grouped[category.id] = {
32582
+ category,
32583
+ apps: []
32584
+ };
32585
+ });
32586
+ this.getAllApps().forEach((app) => {
32587
+ const categoryId = app.category.toLowerCase();
32588
+ if (grouped[categoryId]) {
32589
+ grouped[categoryId].apps.push(app);
32590
+ } else {
32591
+ grouped[categoryId] = {
32592
+ category: { id: categoryId, name: app.category, icon: "📁", color: "#757575" },
32593
+ apps: [app]
32594
+ };
32595
+ }
32596
+ });
32597
+ Object.keys(grouped).forEach((key) => {
32598
+ if (grouped[key].apps.length === 0) {
32599
+ delete grouped[key];
32600
+ }
32601
+ });
32602
+ return grouped;
32603
+ }
32604
+ }
32605
+ const defaultAppManager = new AppManager();
32606
+ const AppContext = React.createContext();
32607
+ const useApplicationMenu = () => {
32608
+ const context = React.useContext(AppContext);
32609
+ if (!context) {
32610
+ throw new Error("useApplicationMenu must be used within AppProvider");
32611
+ }
32612
+ return context.applicationMenu;
32613
+ };
32614
+ const useAppManager = () => {
32615
+ const context = React.useContext(AppContext);
32616
+ if (!context) {
32617
+ throw new Error("useAppManager must be used within AppProvider");
32618
+ }
32619
+ return context.appManager;
32620
+ };
32621
+ const AppProvider = ({ children, appManager = defaultAppManager }) => {
32622
+ const [isApplicationMenuOpen, setIsApplicationMenuOpen] = React.useState(false);
32623
+ const value = {
32624
+ // Application Menu state
32625
+ applicationMenu: {
32626
+ isOpen: isApplicationMenuOpen,
32627
+ open: () => setIsApplicationMenuOpen(true),
32628
+ close: () => setIsApplicationMenuOpen(false),
32629
+ toggle: () => setIsApplicationMenuOpen(!isApplicationMenuOpen)
32630
+ },
32631
+ // App Manager instance
32632
+ appManager
32633
+ };
32634
+ return /* @__PURE__ */ React.createElement(AppContext.Provider, { value }, children);
32635
+ };
32256
32636
  const DesktopLayout = ({ children, className = "", ...props }) => {
32257
32637
  const desktopRef = React.useRef(null);
32258
32638
  const { windowManager } = useWindows();
@@ -32308,7 +32688,7 @@ const rows = [
32308
32688
  toolbar: window2.toolbar,
32309
32689
  statusBar: window2.statusBar
32310
32690
  },
32311
- /* @__PURE__ */ React.createElement("div", { style: { padding: "16px" } }, /* @__PURE__ */ React.createElement("h3", null, "Window: ", window2.title), /* @__PURE__ */ React.createElement("p", null, /* @__PURE__ */ React.createElement("strong", null, "ID:"), " ", window2.id), /* @__PURE__ */ React.createElement("p", null, /* @__PURE__ */ React.createElement("strong", null, "Position:"), " ", window2.position.x, ", ", window2.position.y), /* @__PURE__ */ React.createElement("p", null, /* @__PURE__ */ React.createElement("strong", null, "Size:"), " ", window2.size.width, " × ", window2.size.height), /* @__PURE__ */ React.createElement("p", null, /* @__PURE__ */ React.createElement("strong", null, "Z-Index:"), " ", window2.zIndex), /* @__PURE__ */ React.createElement("p", null, /* @__PURE__ */ React.createElement("strong", null, "Status:"), " ", window2.minimized ? "Minimized" : window2.maximized ? "Maximized" : "Normal"), /* @__PURE__ */ React.createElement("div", { style: { marginTop: "16px", padding: "12px", background: "#f8f9fa", borderRadius: "4px" } }, /* @__PURE__ */ React.createElement("p", null, /* @__PURE__ */ React.createElement("strong", null, "Window Content Area")), /* @__PURE__ */ React.createElement("p", null, "This is where your application content would go."), /* @__PURE__ */ React.createElement("p", null, "The window is fully draggable and has working minimize, maximize, and close buttons.")))
32691
+ /* @__PURE__ */ React.createElement("div", { style: { padding: "16px" } }, window2.content)
32312
32692
  )));
32313
32693
  };
32314
32694
  const DesktopTaskbar = () => {
@@ -32321,6 +32701,7 @@ const rows = [
32321
32701
  minimizeWindow,
32322
32702
  closeWindow
32323
32703
  } = useWindows();
32704
+ const { open: openApplicationMenu } = useApplicationMenu();
32324
32705
  const handleCreateWindow = () => {
32325
32706
  const windowTypes = [
32326
32707
  { title: "File Explorer", icon: "📁", size: { width: 600, height: 400 } },
@@ -32372,12 +32753,34 @@ const rows = [
32372
32753
  padding: "0 16px",
32373
32754
  gap: "8px"
32374
32755
  } }, /* @__PURE__ */ React.createElement(
32756
+ "button",
32757
+ {
32758
+ onClick: openApplicationMenu,
32759
+ style: {
32760
+ padding: "8px 16px",
32761
+ background: "#1976d2",
32762
+ color: "white",
32763
+ border: "none",
32764
+ borderRadius: "4px",
32765
+ cursor: "pointer",
32766
+ fontSize: "14px",
32767
+ fontWeight: "bold",
32768
+ flexShrink: 0,
32769
+ display: "flex",
32770
+ alignItems: "center",
32771
+ gap: "6px"
32772
+ },
32773
+ title: "Open application menu"
32774
+ },
32775
+ /* @__PURE__ */ React.createElement("span", { style: { fontSize: "16px" } }, "🚀"),
32776
+ "Start"
32777
+ ), /* @__PURE__ */ React.createElement(
32375
32778
  "button",
32376
32779
  {
32377
32780
  onClick: handleCreateWindow,
32378
32781
  style: {
32379
32782
  padding: "8px 12px",
32380
- background: "#1976d2",
32783
+ background: "#666",
32381
32784
  color: "white",
32382
32785
  border: "none",
32383
32786
  borderRadius: "4px",
@@ -32385,7 +32788,7 @@ const rows = [
32385
32788
  fontSize: "12px",
32386
32789
  flexShrink: 0
32387
32790
  },
32388
- title: "Create new window"
32791
+ title: "Create random window (for testing)"
32389
32792
  },
32390
32793
  "+"
32391
32794
  ), /* @__PURE__ */ React.createElement("div", { style: {
@@ -32455,8 +32858,18 @@ Middle click: Close`
32455
32858
  textAlign: "right"
32456
32859
  } }, desktopSize.width, "×", desktopSize.height));
32457
32860
  };
32861
+ const DesktopInternal = ({ desktopSize, children, ...props }) => {
32862
+ const { isOpen, close } = useApplicationMenu();
32863
+ return /* @__PURE__ */ React.createElement(WindowProvider, { desktopSize }, /* @__PURE__ */ React.createElement(DesktopLayout, { ...props }, /* @__PURE__ */ React.createElement(Workspace, null, children), /* @__PURE__ */ React.createElement(DesktopTaskbar, null), /* @__PURE__ */ React.createElement(
32864
+ ApplicationMenu,
32865
+ {
32866
+ isOpen,
32867
+ onClose: close
32868
+ }
32869
+ )));
32870
+ };
32458
32871
  const Desktop = ({ desktopSize, children, ...props }) => {
32459
- return /* @__PURE__ */ React.createElement(WindowProvider, { desktopSize }, /* @__PURE__ */ React.createElement(DesktopLayout, { ...props }, /* @__PURE__ */ React.createElement(Workspace, null, children), /* @__PURE__ */ React.createElement(DesktopTaskbar, null)));
32872
+ return /* @__PURE__ */ React.createElement(AppProvider, null, /* @__PURE__ */ React.createElement(DesktopInternal, { desktopSize, ...props }, children));
32460
32873
  };
32461
32874
  const ContentForm = ({ content, columns = 1, filter, rules, onChange }) => {
32462
32875
  const form = content.form();
@@ -42176,6 +42589,9 @@ Middle click: Close`
42176
42589
  exports2.AccordionExamples = AccordionExamples;
42177
42590
  exports2.ActionButton = ActionButton;
42178
42591
  exports2.ActionsCell = ActionsCell;
42592
+ exports2.AppManager = AppManager;
42593
+ exports2.AppProvider = AppProvider;
42594
+ exports2.ApplicationMenu = ApplicationMenu;
42179
42595
  exports2.Avatar = Avatar;
42180
42596
  exports2.Button = Button;
42181
42597
  exports2.ButtonExamples = ButtonExamples;
@@ -42329,8 +42745,11 @@ Middle click: Close`
42329
42745
  exports2.Wizard = Wizard;
42330
42746
  exports2.WizardContext = WizardContext;
42331
42747
  exports2.Workspace = Workspace;
42748
+ exports2.defaultAppManager = defaultAppManager;
42332
42749
  exports2.isEmpty = isEmpty;
42333
42750
  exports2.isFunction = isFunction;
42751
+ exports2.useAppManager = useAppManager;
42752
+ exports2.useApplicationMenu = useApplicationMenu;
42334
42753
  exports2.useCreateWindow = useCreateWindow;
42335
42754
  exports2.useHashPage = useHashPage;
42336
42755
  exports2.useWindow = useWindow;