@articles-media/articles-dev-box 1.5.0 → 1.5.1

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
@@ -68,6 +68,7 @@ npm run dev
68
68
  | GlobalClientModals | Imports all global client modals like FriendsList, CreditsModal, SettingsModal, InfoModal, and so on | USA Tycoon |
69
69
  | generateRandomNickname | Reusable way of doing random nicknames from package | USA Tycoon |
70
70
  | getAssetSource | Gets an assets source location based on the NEXT_PUBLIC_MODEL_SOURCE env value, allows easier/cheaper open sourcing of games by serving public site assets as CDN and dev/cloned site assets locally | School Run |
71
+ | useAssetSource | Like getAssetSource but gets an assets source location based on the useStore state of modelSource. Main difference is this can be changed in game. | School Run |
71
72
  | defaultGameNextConfig | Not usable, for reference | None |
72
73
  | defaultGameThemeConfig | Not usable, for reference | None |
73
74
  | useModalNavigation | Handles navigating a modal with controller | None |
@@ -103,6 +103,7 @@ function MenuButton({ useStore, menuBarConfig }) {
103
103
  * @param {React.ComponentType} [props.menuBarConfig.leftSlotChildren] - Content to render in the left slot of the menu bar.
104
104
  * @param {React.ComponentType} [props.menuBarConfig.centerSlotChildren] - Content to render in the center slot of the menu bar.
105
105
  * @param {React.ComponentType} [props.menuBarConfig.rightSlotChildren] - Content to render in the right slot of the menu bar.
106
+ * @param {React.ComponentType} [props.menuBarConfig.settingsWithMenuButton] - Show settings button inside the menu button.
106
107
  */
107
108
  function GameMenu(props) {
108
109
  const { useStore, LeftPanelContent, sidebarConfig, menuBarConfig } = props;
package/dist/GameMenu.js CHANGED
@@ -1,2 +1,2 @@
1
- import { t as GameMenu } from "./GameMenu-CBn1r9Cq.js";
1
+ import { t as GameMenu } from "./GameMenu-Cu0LB-VG.js";
2
2
  export { GameMenu as default };
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { n as __toESM, t as require_classnames } from "./classnames-No-mjhw1.js";
3
3
  import { n as useMainSiteStatus, t as useAuthSiteStatus } from "./useAuthSiteStatus-DDN0q8T0.js";
4
- import { lazy } from "react";
4
+ import { lazy, useEffect } from "react";
5
5
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
6
6
  //#region src/components/Global/ArticlesDevStatusBadge.jsx
7
7
  var import_classnames = /* @__PURE__ */ __toESM(require_classnames(), 1);
@@ -57,6 +57,31 @@ function ArticlesDevStatusBadge({ useStore }) {
57
57
  })] });
58
58
  }
59
59
  //#endregion
60
+ //#region src/components/UI/ScreenshotModeHandler.jsx
61
+ /**
62
+ * Handles the screenshot mode functionality.
63
+ *
64
+ * @param {function} A Zustand store hook - With screenshotMode and setScreenshotMode
65
+ * @returns {null} Nothing returned from this function.
66
+ */
67
+ function ScreenshotModeHandler({ useStore }) {
68
+ const screenshotMode = useStore((state) => state.screenshotMode);
69
+ const hasHydrated = useStore((state) => state._hasHydrated);
70
+ useEffect(() => {
71
+ const indicator = document.querySelector("[data-nextjs-dev-overlay]");
72
+ if (!hasHydrated) return;
73
+ console.log("screenshotMode changed:", screenshotMode);
74
+ if (screenshotMode) {
75
+ document.body.setAttribute("data-articles-dev-box-screenshot-mode", "enabled");
76
+ if (indicator) indicator.style.display = "none";
77
+ } else {
78
+ document.body.setAttribute("data-articles-dev-box-screenshot-mode", "disabled");
79
+ if (indicator) indicator.style.display = "block";
80
+ }
81
+ }, [screenshotMode, hasHydrated]);
82
+ return /* @__PURE__ */ jsx(Fragment, {});
83
+ }
84
+ //#endregion
60
85
  //#region src/components/Global/GlobalClientModals.jsx
61
86
  var InfoModal = lazy(() => import("./InfoModal.js"));
62
87
  var CreditsModal = lazy(() => import("./CreditsModal.js"));
@@ -112,11 +137,15 @@ function GlobalClientModals({ useStore, useAudioStore, useTouchControlsStore, us
112
137
  setShow: setShowInviteModal,
113
138
  useSocketStore
114
139
  }),
115
- /* @__PURE__ */ jsxs(Fragment, { children: [showDevStatusModal && /* @__PURE__ */ jsx(StatusModal, {
116
- show: showDevStatusModal,
117
- setShow: setShowDevStatusModal,
118
- useSocketStore
119
- }), process.env.NODE_ENV === "development" && /* @__PURE__ */ jsx(ArticlesDevStatusBadge, { useStore })] })
140
+ /* @__PURE__ */ jsxs(Fragment, { children: [
141
+ showDevStatusModal && /* @__PURE__ */ jsx(StatusModal, {
142
+ show: showDevStatusModal,
143
+ setShow: setShowDevStatusModal,
144
+ useSocketStore
145
+ }),
146
+ process.env.NODE_ENV === "development" && /* @__PURE__ */ jsx(ArticlesDevStatusBadge, { useStore }),
147
+ /* @__PURE__ */ jsx(ScreenshotModeHandler, { useStore })
148
+ ] })
120
149
  ] });
121
150
  }
122
151
  //#endregion
@@ -11,6 +11,39 @@ var SessionButton = lazy(() => import("./SessionButton.js"));
11
11
  var ReturnToLauncherButton = lazy(() => import("./ReturnToLauncherButton.js"));
12
12
  var GameScoreboard = lazy(() => import("./GameScoreboard.js"));
13
13
  var Ad = lazy(() => import("./Ad.js"));
14
+ /**
15
+ * Landing page template for a game with single/multiplayer options, scoreboard and ads.
16
+ *
17
+ * @param {Object} props - Component props
18
+ * @param {Function} props.useStore - Zustand (or similar) store hook
19
+ * @param {Function} props.useSocketStore - Socket store hook
20
+ * @param {React.Component|Function|Node} props.RotatingMascot - Mascot component or node
21
+ * @param {Function} props.Link - Router Link component
22
+ * @param {string} props.logoImage - URL for the logo image
23
+ * @param {string} props.backgroundImage - URL for the background image
24
+ * @param {React.Node} [props.CardBodyOverride] - Overrides the default card body
25
+ * @param {React.Node} [props.CardBodyAppendContent] - Content appended to card body
26
+ * @param {React.Node} [props.CardBodyPrependContent] - Content prepended to card body
27
+ * @param {Object} [props.singlePlayerConfig] - Single player configuration
28
+ * @param {Object} [props.multiplayerConfig] - Multiplayer configuration
29
+ * @param {string} [props.brandingTextClass] - Extra class for branding text
30
+ * @param {boolean} [props.disableHero] - Disable hero section
31
+ * @param {React.Node} [props.heroOverride] - Override for hero area
32
+ * @param {boolean} [props.disableAd] - Disable ad slot
33
+ * @param {boolean} [props.disableGameScoreboard] - Disable scoreboard
34
+ * @param {Object} [props.gameScoreboardConfig] - Config for scoreboard
35
+ * @param {string|number} [props.maxInnerWidth] - Max inner width (CSS value)
36
+ * @param {React.Node} [props.AdditionalContent] - Additional top-level content
37
+ * @param {React.Node} [props.PostCardContent] - Content shown after the card
38
+ * @param {React.Node} [props.PostExtrasContent] - Content shown after extras
39
+ * @param {React.Node} [props.PreHeroContent] - Content shown before hero
40
+ * @param {React.Node} [props.PostHeroContent] - Content shown after hero
41
+ * @param {Object} [props.NicknameInputConfig] - Config for `NicknameInput`
42
+ * @param {React.Node} [props.CardOverride] - Completely override the card
43
+ * @param {React.Node} [props.LandingBackgroundAnimation] - Optional background animation node
44
+ * @param {Function} [props.useRouter] - Router hook (optional)
45
+ * @returns {React.Element} Landing page element
46
+ */
14
47
  function PageTemplateLandingPage({ useStore, useSocketStore, RotatingMascot, Link, logoImage, backgroundImage, CardBodyOverride, CardBodyAppendContent, CardBodyPrependContent, singlePlayerConfig, multiplayerConfig, brandingTextClass, disableHero, heroOverride, disableAd, disableGameScoreboard, gameScoreboardConfig, maxInnerWidth = "20rem", AdditionalContent = null, PostCardContent = null, PostExtrasContent = null, PreHeroContent = null, PostHeroContent = null, NicknameInputConfig = null, CardOverride = null, LandingBackgroundAnimation = null, useRouter = null }) {
15
48
  const { data: userToken, error: userTokenError, isLoading: userTokenLoading, mutate: userTokenMutate } = useUserToken(process.env.NEXT_PUBLIC_GAME_PORT);
16
49
  const { data: userDetails, error: userDetailsError, isLoading: userDetailsLoading, mutate: userDetailsMutate } = useUserDetails({ token: userToken });
@@ -142,6 +175,15 @@ function PageTemplateLandingPage({ useStore, useSocketStore, RotatingMascot, Lin
142
175
  ]
143
176
  });
144
177
  }
178
+ /**
179
+ * Server list renderer used on the landing page. Shows available servers and join buttons.
180
+ *
181
+ * @param {Object} props
182
+ * @param {Function} props.useStore - Store hook to access lobby details
183
+ * @param {Object} props.multiplayerConfig - Multiplayer configuration (e.g. defaultServers)
184
+ * @param {Function|Component} props.Link - Router Link component
185
+ * @returns {React.Element}
186
+ */
145
187
  function Servers({ useStore, multiplayerConfig, Link }) {
146
188
  const lobbyDetails = useStore((state) => state.lobbyDetails);
147
189
  useStore((state) => state.lobbyDetails.online_player_count);
@@ -205,6 +247,14 @@ function Servers({ useStore, multiplayerConfig, Link }) {
205
247
  })
206
248
  });
207
249
  }
250
+ /**
251
+ * Online players summary component.
252
+ *
253
+ * @param {Object} props
254
+ * @param {Function} props.useStore - Store hook to access lobby/player counts
255
+ * @param {Object} props.multiplayerConfig - Multiplayer configuration defining templates
256
+ * @returns {React.Element}
257
+ */
208
258
  function OnlinePlayers({ useStore, multiplayerConfig }) {
209
259
  const lobbyDetails = useStore((state) => state.lobbyDetails);
210
260
  const landing_player_count = useStore((state) => state.lobbyDetails.landing_player_count);
@@ -128,6 +128,8 @@ function ReusedSocketLogicHandler({ pathname, useStore, useGameStore, useSocketS
128
128
  }
129
129
  }, [debugConfig.enabled]);
130
130
  if (debugConfig.enabled && isVisible && process.env.NODE_ENV !== "production") return /* @__PURE__ */ jsxs("div", {
131
+ id: "articles-dev-box-socket-debug-overlay",
132
+ className: "test",
131
133
  style: {
132
134
  position: "fixed",
133
135
  bottom: 0,
@@ -246,7 +246,7 @@ function OtherTab({ useStore, config }) {
246
246
  var package_default = {
247
247
  name: "@articles-media/articles-dev-box",
248
248
  description: "Shared code, functions, and components for different Articles Media projects.",
249
- version: "1.5.0",
249
+ version: "1.5.1",
250
250
  type: "module",
251
251
  sideEffects: false,
252
252
  imports: { "#root/src/*": "./src/*" },
@@ -1,2 +1,2 @@
1
- import { t as SettingsModal } from "./SettingsModal-DOJp07_e.js";
1
+ import { t as SettingsModal } from "./SettingsModal-9wsM2qrD.js";
2
2
  export { SettingsModal as default };
@@ -488,6 +488,13 @@
488
488
  bottom: 50%;
489
489
  transform: translateY(50%);
490
490
  left: 8px;
491
+ }body[data-articles-dev-box-screenshot-mode=enabled] .articles-dev-status,
492
+ body[data-articles-dev-box-screenshot-mode=enabled] .dev-box-game-menu,
493
+ body[data-articles-dev-box-screenshot-mode=enabled] .hide-in-screenshot-mode,
494
+ body[data-articles-dev-box-screenshot-mode=enabled] #articles-dev-box-socket-debug-overlay,
495
+ body[data-articles-dev-box-screenshot-mode=enabled] .show-sidebar .panel-left.dev-box-game-menu,
496
+ body[data-articles-dev-box-screenshot-mode=enabled] #devtools-indicator {
497
+ display: none !important;
491
498
  }.articles-settings-modal input[type=range]::-webkit-slider-runnable-track {
492
499
  background: #000;
493
500
  height: 0.5rem;
package/dist/index.js CHANGED
@@ -8,7 +8,7 @@ import useUserFriends from "./useUserFriends.js";
8
8
  import FriendsList from "./FriendsList.js";
9
9
  import { t as SessionButton } from "./SessionButton-D0EcgEPz.js";
10
10
  import ArticlesAd from "./ArticlesAd.js";
11
- import { t as GameMenu } from "./GameMenu-CBn1r9Cq.js";
11
+ import { t as GameMenu } from "./GameMenu-Cu0LB-VG.js";
12
12
  import useFullscreen from "./useFullscreen.js";
13
13
  import PrimaryButtonGroup from "./GameMenuPrimaryButtonGroup.js";
14
14
  import NicknameInput from "./NicknameInput.js";
@@ -16,7 +16,7 @@ import { t as GameScoreboard } from "./GameScoreboard-BvE_sIDW.js";
16
16
  import PageTemplateLandingPage from "./PageTemplateLandingPage.js";
17
17
  import GlobalHead from "./GlobalHead.js";
18
18
  import GlobalBody_default from "./GlobalBody.js";
19
- import { t as SettingsModal } from "./SettingsModal-DOJp07_e.js";
19
+ import { t as SettingsModal } from "./SettingsModal-9wsM2qrD.js";
20
20
  import CreditsModal from "./CreditsModal.js";
21
21
  import InfoModal from "./InfoModal.js";
22
22
  import DarkModeHandler from "./DarkModeHandler.js";
@@ -107,7 +107,10 @@ var typicalZustandStoreStateSlice = (set, get, generateRandomNickname) => ({
107
107
  isTouchCapable: null,
108
108
  setIsTouchCapable: (value) => set({ isTouchCapable: value }),
109
109
  modelSource: process.env.NEXT_PUBLIC_MODEL_SOURCE || "Local",
110
- setModelSource: (value) => set({ modelSource: value })
110
+ setModelSource: (value) => set({ modelSource: value }),
111
+ screenshotMode: false,
112
+ setScreenshotMode: (value) => set({ screenshotMode: value }),
113
+ toggleScreenshotMode: () => set({ screenshotMode: !get().screenshotMode })
111
114
  });
112
115
  //#endregion
113
116
  export { typicalZustandStoreStateSlice as default };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@articles-media/articles-dev-box",
3
3
  "description": "Shared code, functions, and components for different Articles Media projects.",
4
- "version": "1.5.0",
4
+ "version": "1.5.1",
5
5
  "type": "module",
6
6
  "sideEffects": false,
7
7
  "imports": {