@edx/frontend-platform 8.2.1 → 8.3.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/config.js CHANGED
@@ -134,6 +134,40 @@ function extractRegex(envVar) {
134
134
  }
135
135
  return undefined;
136
136
  }
137
+
138
+ /**
139
+ * Safely parses a JSON string coming from the environment variables.
140
+ * If the JSON is invalid, the function returns an empty object and logs an error to the console.
141
+ *
142
+ * @param {string} paragonUrlsJson - The JSON string representing Paragon theme URLs.
143
+ * @returns {Object|undefined} - Returns a parsed object if the JSON is valid; otherwise, returns
144
+ * an empty object if invalid or undefined if no input is provided.
145
+ *
146
+ * @example
147
+ * const jsonString = '{
148
+ * "core":{"urls":{"default":"core.min.css"}},
149
+ * "defaults":{"light":"light"},
150
+ * "variants":{"light":{"urls":{"default":"light.min.css"}}}
151
+ * }';
152
+ * const parsedUrls = parseParagonThemeUrls(jsonString);
153
+ * console.log(parsedUrls); // Outputs the parsed JSON object
154
+ */
155
+ function parseParagonThemeUrls(paragonUrlsJson) {
156
+ if (!paragonUrlsJson) {
157
+ return undefined;
158
+ }
159
+ try {
160
+ return JSON.parse(paragonUrlsJson);
161
+ } catch (err) {
162
+ if (err instanceof SyntaxError) {
163
+ // eslint-disable-next-line no-console
164
+ console.error('Unable to parse PARAGON_THEME_URLS JSON.\nPlease check https://github.com/openedx/frontend-platform/tree/master/docs/how_tos/theming.md for the expected formatting.\nAn empty object ({}) will be returned, which will cause the theming configuration to fall back to the installed packages.');
165
+ return {};
166
+ }
167
+ // In case of a different type of error, return the error object itself
168
+ return err;
169
+ }
170
+ }
137
171
  var ENVIRONMENT = process.env.NODE_ENV;
138
172
  var config = {
139
173
  ACCESS_TOKEN_COOKIE_NAME: process.env.ACCESS_TOKEN_COOKIE_NAME,
@@ -167,7 +201,8 @@ var config = {
167
201
  FAVICON_URL: process.env.FAVICON_URL,
168
202
  MFE_CONFIG_API_URL: process.env.MFE_CONFIG_API_URL,
169
203
  APP_ID: process.env.APP_ID,
170
- SUPPORT_URL: process.env.SUPPORT_URL
204
+ SUPPORT_URL: process.env.SUPPORT_URL,
205
+ PARAGON_THEME_URLS: parseParagonThemeUrls(process.env.PARAGON_THEME_URLS)
171
206
  };
172
207
 
173
208
  /**
@@ -322,5 +357,6 @@ export function ensureConfig(keys) {
322
357
  * @property {string} MFE_CONFIG_API_URL
323
358
  * @property {string} APP_ID
324
359
  * @property {string} SUPPORT_URL
360
+ * @property {string} PARAGON_THEME_URLS
325
361
  */
326
362
  //# sourceMappingURL=config.js.map
package/config.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","names":["APP_CONFIG_INITIALIZED","CONFIG_CHANGED","publish","subscribe","ensureDefinedConfig","extractRegex","envVar","trim","RegExp","undefined","ENVIRONMENT","process","env","NODE_ENV","config","ACCESS_TOKEN_COOKIE_NAME","ACCOUNT_PROFILE_URL","ACCOUNT_SETTINGS_URL","BASE_URL","PUBLIC_PATH","CREDENTIALS_BASE_URL","CSRF_TOKEN_API_PATH","DISCOVERY_API_BASE_URL","PUBLISHER_BASE_URL","ECOMMERCE_BASE_URL","IGNORED_ERROR_REGEX","LANGUAGE_PREFERENCE_COOKIE_NAME","LEARNING_BASE_URL","LMS_BASE_URL","LOGIN_URL","LOGOUT_URL","STUDIO_BASE_URL","MARKETING_SITE_BASE_URL","ORDER_HISTORY_URL","REFRESH_ACCESS_TOKEN_ENDPOINT","SECURE_COOKIES","SEGMENT_KEY","SITE_NAME","USER_INFO_COOKIE_NAME","LOGO_URL","LOGO_TRADEMARK_URL","LOGO_WHITE_URL","FAVICON_URL","MFE_CONFIG_API_URL","APP_ID","SUPPORT_URL","getConfig","setConfig","newConfig","mergeConfig","Object","assign","ensureConfig","keys","requester","arguments","length","forEach","key","console","warn","concat"],"sources":["../src/config.js"],"sourcesContent":["/**\n * #### Import members from **@edx/frontend-platform**\n *\n * The configuration module provides utilities for working with an application's configuration\n * document (ConfigDocument). Configuration variables can be supplied to the\n * application in four different ways. They are applied in the following order:\n *\n * - Build-time Configuration\n * - Environment Variables\n * - JavaScript File\n * - Runtime Configuration\n *\n * Last one in wins. Variables with the same name defined via the later methods will override any\n * defined using an earlier method. i.e., if a variable is defined in Runtime Configuration, that\n * will override the same variable defined in either Build-time Configuration method (environment\n * variables or JS file). Configuration defined in a JS file will override environment variables.\n *\n * ##### Build-time Configuration\n *\n * Build-time configuration methods add config variables into the app when it is built by webpack.\n * This saves the app an API call and means it has all the information it needs to initialize right\n * away. There are two methods of supplying build-time configuration: environment variables and a\n * JavaScript file.\n *\n * ###### Environment Variables\n *\n * A set list of required config variables can be supplied as\n * command-line environment variables during the build process.\n *\n * As a simple example, these are supplied on the command-line before invoking `npm run build`:\n *\n * ```\n * LMS_BASE_URL=http://localhost:18000 npm run build\n * ```\n *\n * Note that additional variables _cannot_ be supplied via this method without using the `config`\n * initialization handler. The app won't pick them up and they'll appear `undefined`.\n *\n * This configuration method is being deprecated in favor of JavaScript File Configuration.\n *\n * ###### JavaScript File Configuration\n *\n * Configuration variables can be supplied in an optional file named env.config.js. This file must\n * export either an Object containing configuration variables or a function. The function must\n * return an Object containing configuration variables or, alternately, a promise which resolves to\n * an Object.\n *\n * Using a function or async function allows the configuration to be resolved at runtime (because\n * the function will be executed at runtime). This is not common, and the capability is included\n * for the sake of flexibility.\n *\n * JavaScript File Configuration is well-suited to extensibility use cases or component overrides,\n * in that the configuration file can depend on any installed JavaScript module. It is also the\n * preferred way of doing build-time configuration if runtime configuration isn't used by your\n * deployment of the platform.\n *\n * Exporting a config object:\n * ```\n * const config = {\n * LMS_BASE_URL: 'http://localhost:18000'\n * };\n *\n * export default config;\n * ```\n *\n * Exporting a function that returns an object:\n * ```\n * function getConfig() {\n * return {\n * LMS_BASE_URL: 'http://localhost:18000'\n * };\n * }\n * ```\n *\n * Exporting a function that returns a promise that resolves to an object:\n * ```\n * function getAsyncConfig() {\n * return new Promise((resolve, reject) => {\n * resolve({\n * LMS_BASE_URL: 'http://localhost:18000'\n * });\n * });\n * }\n *\n * export default getAsyncConfig;\n * ```\n *\n * ##### Runtime Configuration\n *\n * Configuration variables can also be supplied using the \"runtime configuration\" method, taking\n * advantage of the Micro-frontend Config API in edx-platform. More information on this API can be\n * found in the ADR which introduced it:\n *\n * https://github.com/openedx/edx-platform/blob/master/lms/djangoapps/mfe_config_api/docs/decisions/0001-mfe-config-api.rst\n *\n * The runtime configuration method can be enabled by supplying a MFE_CONFIG_API_URL via one of the other\n * two configuration methods above.\n *\n * Runtime configuration is particularly useful if you need to supply different configurations to\n * a single deployment of a micro-frontend, for instance. It is also a perfectly valid alternative\n * to build-time configuration, though it introduces an additional API call to edx-platform on MFE\n * initialization.\n *\n * ##### Initialization Config Handler\n *\n * The configuration document can be extended by\n * applications at run-time using a `config` initialization handler. Please see the Initialization\n * documentation for more information on handlers and initialization phases.\n *\n * ```\n * initialize({\n * handlers: {\n * config: () => {\n * mergeConfig({\n * CUSTOM_VARIABLE: 'custom value',\n * LMS_BASE_URL: 'http://localhost:18001' // You can override variables, but this is uncommon.\n * }, 'App config override handler');\n * },\n * },\n * });\n * ```\n *\n * @module Config\n */\n\nimport { APP_CONFIG_INITIALIZED, CONFIG_CHANGED } from './constants';\n\nimport { publish, subscribe } from './pubSub';\nimport { ensureDefinedConfig } from './utils';\n\nfunction extractRegex(envVar) {\n // Convert the environment variable string to a regex, while guarding\n // against a non-string and an empty/whitespace-only string.\n if (typeof envVar === 'string' && envVar.trim() !== '') {\n return new RegExp(envVar);\n }\n return undefined;\n}\n\nconst ENVIRONMENT = process.env.NODE_ENV;\nlet config = {\n ACCESS_TOKEN_COOKIE_NAME: process.env.ACCESS_TOKEN_COOKIE_NAME,\n ACCOUNT_PROFILE_URL: process.env.ACCOUNT_PROFILE_URL,\n ACCOUNT_SETTINGS_URL: process.env.ACCOUNT_SETTINGS_URL,\n BASE_URL: process.env.BASE_URL,\n PUBLIC_PATH: process.env.PUBLIC_PATH || '/',\n CREDENTIALS_BASE_URL: process.env.CREDENTIALS_BASE_URL,\n CSRF_TOKEN_API_PATH: process.env.CSRF_TOKEN_API_PATH,\n DISCOVERY_API_BASE_URL: process.env.DISCOVERY_API_BASE_URL,\n PUBLISHER_BASE_URL: process.env.PUBLISHER_BASE_URL,\n ECOMMERCE_BASE_URL: process.env.ECOMMERCE_BASE_URL,\n ENVIRONMENT,\n IGNORED_ERROR_REGEX: extractRegex(process.env.IGNORED_ERROR_REGEX),\n LANGUAGE_PREFERENCE_COOKIE_NAME: process.env.LANGUAGE_PREFERENCE_COOKIE_NAME,\n LEARNING_BASE_URL: process.env.LEARNING_BASE_URL,\n LMS_BASE_URL: process.env.LMS_BASE_URL,\n LOGIN_URL: process.env.LOGIN_URL,\n LOGOUT_URL: process.env.LOGOUT_URL,\n STUDIO_BASE_URL: process.env.STUDIO_BASE_URL,\n MARKETING_SITE_BASE_URL: process.env.MARKETING_SITE_BASE_URL,\n ORDER_HISTORY_URL: process.env.ORDER_HISTORY_URL,\n REFRESH_ACCESS_TOKEN_ENDPOINT: process.env.REFRESH_ACCESS_TOKEN_ENDPOINT,\n SECURE_COOKIES: ENVIRONMENT !== 'development',\n SEGMENT_KEY: process.env.SEGMENT_KEY,\n SITE_NAME: process.env.SITE_NAME,\n USER_INFO_COOKIE_NAME: process.env.USER_INFO_COOKIE_NAME,\n LOGO_URL: process.env.LOGO_URL,\n LOGO_TRADEMARK_URL: process.env.LOGO_TRADEMARK_URL,\n LOGO_WHITE_URL: process.env.LOGO_WHITE_URL,\n FAVICON_URL: process.env.FAVICON_URL,\n MFE_CONFIG_API_URL: process.env.MFE_CONFIG_API_URL,\n APP_ID: process.env.APP_ID,\n SUPPORT_URL: process.env.SUPPORT_URL,\n};\n\n/**\n * Getter for the application configuration document. This is synchronous and merely returns a\n * reference to an existing object, and is thus safe to call as often as desired.\n *\n * Example:\n *\n * ```\n * import { getConfig } from '@edx/frontend-platform';\n *\n * const {\n * LMS_BASE_URL,\n * } = getConfig();\n * ```\n *\n * @returns {ConfigDocument}\n */\nexport function getConfig() {\n return config;\n}\n\n/**\n * Replaces the existing ConfigDocument. This is not commonly used, but can be helpful for tests.\n *\n * The supplied config document will be tested with `ensureDefinedConfig` to ensure it does not\n * have any `undefined` keys.\n *\n * Example:\n *\n * ```\n * import { setConfig } from '@edx/frontend-platform';\n *\n * setConfig({\n * LMS_BASE_URL, // This is overriding the ENTIRE document - this is not merged in!\n * });\n * ```\n *\n * @param {ConfigDocument} newConfig\n */\nexport function setConfig(newConfig) {\n ensureDefinedConfig(config, 'config');\n config = newConfig;\n publish(CONFIG_CHANGED);\n}\n\n/**\n * Merges additional configuration values into the ConfigDocument returned by `getConfig`. Will\n * override any values that exist with the same keys.\n *\n * ```\n * mergeConfig({\n * NEW_KEY: 'new value',\n * OTHER_NEW_KEY: 'other new value',\n * });\n *\n * If any of the key values are `undefined`, an error will be logged to 'warn'.\n *\n * @param {Object} newConfig\n */\nexport function mergeConfig(newConfig) {\n ensureDefinedConfig(newConfig, 'ProcessEnvConfigService');\n config = Object.assign(config, newConfig);\n publish(CONFIG_CHANGED);\n}\n\n/**\n * A method allowing application code to indicate that particular ConfigDocument keys are required\n * for them to function. This is useful for diagnosing development/deployment issues, primarily,\n * by surfacing misconfigurations early. For instance, if the build process fails to supply an\n * environment variable on the command-line, it's possible that one of the `process.env` variables\n * will be undefined. Should be used in conjunction with `mergeConfig` for custom `ConfigDocument`\n * properties. Requester is for informational/error reporting purposes only.\n *\n * ```\n * ensureConfig(['LMS_BASE_URL', 'LOGIN_URL'], 'MySpecialComponent');\n *\n * // Will log a warning with:\n * // \"App configuration error: LOGIN_URL is required by MySpecialComponent.\"\n * // if LOGIN_URL is undefined, for example.\n * ```\n *\n * *NOTE*: `ensureConfig` waits until `APP_CONFIG_INITIALIZED` is published to verify the existence\n * of the specified properties. This means that this function is compatible with custom `config`\n * phase handlers responsible for loading additional configuration data in the initialization\n * sequence.\n *\n * @param {Array} keys\n * @param {string} [requester='unspecified application code']\n */\nexport function ensureConfig(keys, requester = 'unspecified application code') {\n subscribe(APP_CONFIG_INITIALIZED, () => {\n keys.forEach((key) => {\n if (config[key] === undefined) {\n // eslint-disable-next-line no-console\n console.warn(`App configuration error: ${key} is required by ${requester}.`);\n }\n });\n });\n}\n\n/**\n * An object describing the current application configuration.\n *\n * In its most basic form, the initialization process loads this document via `process.env`\n * variables. There are other ways to add configuration variables to the ConfigDocument as\n * documented above (JavaScript File Configuration, Runtime Configuration, and the Initialization\n * Config Handler)\n *\n * ```\n * {\n * BASE_URL: process.env.BASE_URL,\n * // ... other vars\n * }\n * ```\n *\n * When using Webpack (i.e., normal usage), the build process is responsible for supplying these\n * variables via command-line environment variables. That means they must be supplied at build\n * time.\n *\n * @name ConfigDocument\n * @memberof module:Config\n * @property {string} ACCESS_TOKEN_COOKIE_NAME\n * @property {string} ACCOUNT_PROFILE_URL\n * @property {string} ACCOUNT_SETTINGS_URL\n * @property {string} BASE_URL The URL of the current application.\n * @property {string} CREDENTIALS_BASE_URL\n * @property {string} CSRF_TOKEN_API_PATH\n * @property {string} DISCOVERY_API_BASE_URL\n * @property {string} PUBLISHER_BASE_URL\n * @property {string} ECOMMERCE_BASE_URL\n * @property {string} ENVIRONMENT This is one of: development, production, or test.\n * @property {string} IGNORED_ERROR_REGEX\n * @property {string} LANGUAGE_PREFERENCE_COOKIE_NAME\n * @property {string} LEARNING_BASE_URL\n * @property {string} LMS_BASE_URL\n * @property {string} LOGIN_URL\n * @property {string} LOGOUT_URL\n * @property {string} STUDIO_BASE_URL\n * @property {string} MARKETING_SITE_BASE_URL\n * @property {string} ORDER_HISTORY_URL\n * @property {string} REFRESH_ACCESS_TOKEN_ENDPOINT\n * @property {boolean} SECURE_COOKIES\n * @property {string} SEGMENT_KEY\n * @property {string} SITE_NAME\n * @property {string} USER_INFO_COOKIE_NAME\n * @property {string} LOGO_URL\n * @property {string} LOGO_TRADEMARK_URL\n * @property {string} LOGO_WHITE_URL\n * @property {string} FAVICON_URL\n * @property {string} MFE_CONFIG_API_URL\n * @property {string} APP_ID\n * @property {string} SUPPORT_URL\n */\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,SAASA,sBAAsB,EAAEC,cAAc,QAAQ,aAAa;AAEpE,SAASC,OAAO,EAAEC,SAAS,QAAQ,UAAU;AAC7C,SAASC,mBAAmB,QAAQ,SAAS;AAE7C,SAASC,YAAYA,CAACC,MAAM,EAAE;EAC5B;EACA;EACA,IAAI,OAAOA,MAAM,KAAK,QAAQ,IAAIA,MAAM,CAACC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE;IACtD,OAAO,IAAIC,MAAM,CAACF,MAAM,CAAC;EAC3B;EACA,OAAOG,SAAS;AAClB;AAEA,IAAMC,WAAW,GAAGC,OAAO,CAACC,GAAG,CAACC,QAAQ;AACxC,IAAIC,MAAM,GAAG;EACXC,wBAAwB,EAAEJ,OAAO,CAACC,GAAG,CAACG,wBAAwB;EAC9DC,mBAAmB,EAAEL,OAAO,CAACC,GAAG,CAACI,mBAAmB;EACpDC,oBAAoB,EAAEN,OAAO,CAACC,GAAG,CAACK,oBAAoB;EACtDC,QAAQ,EAAEP,OAAO,CAACC,GAAG,CAACM,QAAQ;EAC9BC,WAAW,EAAER,OAAO,CAACC,GAAG,CAACO,WAAW,IAAI,GAAG;EAC3CC,oBAAoB,EAAET,OAAO,CAACC,GAAG,CAACQ,oBAAoB;EACtDC,mBAAmB,EAAEV,OAAO,CAACC,GAAG,CAACS,mBAAmB;EACpDC,sBAAsB,EAAEX,OAAO,CAACC,GAAG,CAACU,sBAAsB;EAC1DC,kBAAkB,EAAEZ,OAAO,CAACC,GAAG,CAACW,kBAAkB;EAClDC,kBAAkB,EAAEb,OAAO,CAACC,GAAG,CAACY,kBAAkB;EAClDd,WAAW,EAAXA,WAAW;EACXe,mBAAmB,EAAEpB,YAAY,CAACM,OAAO,CAACC,GAAG,CAACa,mBAAmB,CAAC;EAClEC,+BAA+B,EAAEf,OAAO,CAACC,GAAG,CAACc,+BAA+B;EAC5EC,iBAAiB,EAAEhB,OAAO,CAACC,GAAG,CAACe,iBAAiB;EAChDC,YAAY,EAAEjB,OAAO,CAACC,GAAG,CAACgB,YAAY;EACtCC,SAAS,EAAElB,OAAO,CAACC,GAAG,CAACiB,SAAS;EAChCC,UAAU,EAAEnB,OAAO,CAACC,GAAG,CAACkB,UAAU;EAClCC,eAAe,EAAEpB,OAAO,CAACC,GAAG,CAACmB,eAAe;EAC5CC,uBAAuB,EAAErB,OAAO,CAACC,GAAG,CAACoB,uBAAuB;EAC5DC,iBAAiB,EAAEtB,OAAO,CAACC,GAAG,CAACqB,iBAAiB;EAChDC,6BAA6B,EAAEvB,OAAO,CAACC,GAAG,CAACsB,6BAA6B;EACxEC,cAAc,EAAEzB,WAAW,KAAK,aAAa;EAC7C0B,WAAW,EAAEzB,OAAO,CAACC,GAAG,CAACwB,WAAW;EACpCC,SAAS,EAAE1B,OAAO,CAACC,GAAG,CAACyB,SAAS;EAChCC,qBAAqB,EAAE3B,OAAO,CAACC,GAAG,CAAC0B,qBAAqB;EACxDC,QAAQ,EAAE5B,OAAO,CAACC,GAAG,CAAC2B,QAAQ;EAC9BC,kBAAkB,EAAE7B,OAAO,CAACC,GAAG,CAAC4B,kBAAkB;EAClDC,cAAc,EAAE9B,OAAO,CAACC,GAAG,CAAC6B,cAAc;EAC1CC,WAAW,EAAE/B,OAAO,CAACC,GAAG,CAAC8B,WAAW;EACpCC,kBAAkB,EAAEhC,OAAO,CAACC,GAAG,CAAC+B,kBAAkB;EAClDC,MAAM,EAAEjC,OAAO,CAACC,GAAG,CAACgC,MAAM;EAC1BC,WAAW,EAAElC,OAAO,CAACC,GAAG,CAACiC;AAC3B,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,SAASA,CAAA,EAAG;EAC1B,OAAOhC,MAAM;AACf;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASiC,SAASA,CAACC,SAAS,EAAE;EACnC5C,mBAAmB,CAACU,MAAM,EAAE,QAAQ,CAAC;EACrCA,MAAM,GAAGkC,SAAS;EAClB9C,OAAO,CAACD,cAAc,CAAC;AACzB;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASgD,WAAWA,CAACD,SAAS,EAAE;EACrC5C,mBAAmB,CAAC4C,SAAS,EAAE,yBAAyB,CAAC;EACzDlC,MAAM,GAAGoC,MAAM,CAACC,MAAM,CAACrC,MAAM,EAAEkC,SAAS,CAAC;EACzC9C,OAAO,CAACD,cAAc,CAAC;AACzB;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASmD,YAAYA,CAACC,IAAI,EAA8C;EAAA,IAA5CC,SAAS,GAAAC,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAA9C,SAAA,GAAA8C,SAAA,MAAG,8BAA8B;EAC3EpD,SAAS,CAACH,sBAAsB,EAAE,YAAM;IACtCqD,IAAI,CAACI,OAAO,CAAC,UAACC,GAAG,EAAK;MACpB,IAAI5C,MAAM,CAAC4C,GAAG,CAAC,KAAKjD,SAAS,EAAE;QAC7B;QACAkD,OAAO,CAACC,IAAI,6BAAAC,MAAA,CAA6BH,GAAG,sBAAAG,MAAA,CAAmBP,SAAS,MAAG,CAAC;MAC9E;IACF,CAAC,CAAC;EACJ,CAAC,CAAC;AACJ;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","ignoreList":[]}
1
+ {"version":3,"file":"config.js","names":["APP_CONFIG_INITIALIZED","CONFIG_CHANGED","publish","subscribe","ensureDefinedConfig","extractRegex","envVar","trim","RegExp","undefined","parseParagonThemeUrls","paragonUrlsJson","JSON","parse","err","SyntaxError","console","error","ENVIRONMENT","process","env","NODE_ENV","config","ACCESS_TOKEN_COOKIE_NAME","ACCOUNT_PROFILE_URL","ACCOUNT_SETTINGS_URL","BASE_URL","PUBLIC_PATH","CREDENTIALS_BASE_URL","CSRF_TOKEN_API_PATH","DISCOVERY_API_BASE_URL","PUBLISHER_BASE_URL","ECOMMERCE_BASE_URL","IGNORED_ERROR_REGEX","LANGUAGE_PREFERENCE_COOKIE_NAME","LEARNING_BASE_URL","LMS_BASE_URL","LOGIN_URL","LOGOUT_URL","STUDIO_BASE_URL","MARKETING_SITE_BASE_URL","ORDER_HISTORY_URL","REFRESH_ACCESS_TOKEN_ENDPOINT","SECURE_COOKIES","SEGMENT_KEY","SITE_NAME","USER_INFO_COOKIE_NAME","LOGO_URL","LOGO_TRADEMARK_URL","LOGO_WHITE_URL","FAVICON_URL","MFE_CONFIG_API_URL","APP_ID","SUPPORT_URL","PARAGON_THEME_URLS","getConfig","setConfig","newConfig","mergeConfig","Object","assign","ensureConfig","keys","requester","arguments","length","forEach","key","warn","concat"],"sources":["../src/config.js"],"sourcesContent":["/**\n * #### Import members from **@edx/frontend-platform**\n *\n * The configuration module provides utilities for working with an application's configuration\n * document (ConfigDocument). Configuration variables can be supplied to the\n * application in four different ways. They are applied in the following order:\n *\n * - Build-time Configuration\n * - Environment Variables\n * - JavaScript File\n * - Runtime Configuration\n *\n * Last one in wins. Variables with the same name defined via the later methods will override any\n * defined using an earlier method. i.e., if a variable is defined in Runtime Configuration, that\n * will override the same variable defined in either Build-time Configuration method (environment\n * variables or JS file). Configuration defined in a JS file will override environment variables.\n *\n * ##### Build-time Configuration\n *\n * Build-time configuration methods add config variables into the app when it is built by webpack.\n * This saves the app an API call and means it has all the information it needs to initialize right\n * away. There are two methods of supplying build-time configuration: environment variables and a\n * JavaScript file.\n *\n * ###### Environment Variables\n *\n * A set list of required config variables can be supplied as\n * command-line environment variables during the build process.\n *\n * As a simple example, these are supplied on the command-line before invoking `npm run build`:\n *\n * ```\n * LMS_BASE_URL=http://localhost:18000 npm run build\n * ```\n *\n * Note that additional variables _cannot_ be supplied via this method without using the `config`\n * initialization handler. The app won't pick them up and they'll appear `undefined`.\n *\n * This configuration method is being deprecated in favor of JavaScript File Configuration.\n *\n * ###### JavaScript File Configuration\n *\n * Configuration variables can be supplied in an optional file named env.config.js. This file must\n * export either an Object containing configuration variables or a function. The function must\n * return an Object containing configuration variables or, alternately, a promise which resolves to\n * an Object.\n *\n * Using a function or async function allows the configuration to be resolved at runtime (because\n * the function will be executed at runtime). This is not common, and the capability is included\n * for the sake of flexibility.\n *\n * JavaScript File Configuration is well-suited to extensibility use cases or component overrides,\n * in that the configuration file can depend on any installed JavaScript module. It is also the\n * preferred way of doing build-time configuration if runtime configuration isn't used by your\n * deployment of the platform.\n *\n * Exporting a config object:\n * ```\n * const config = {\n * LMS_BASE_URL: 'http://localhost:18000'\n * };\n *\n * export default config;\n * ```\n *\n * Exporting a function that returns an object:\n * ```\n * function getConfig() {\n * return {\n * LMS_BASE_URL: 'http://localhost:18000'\n * };\n * }\n * ```\n *\n * Exporting a function that returns a promise that resolves to an object:\n * ```\n * function getAsyncConfig() {\n * return new Promise((resolve, reject) => {\n * resolve({\n * LMS_BASE_URL: 'http://localhost:18000'\n * });\n * });\n * }\n *\n * export default getAsyncConfig;\n * ```\n *\n * ##### Runtime Configuration\n *\n * Configuration variables can also be supplied using the \"runtime configuration\" method, taking\n * advantage of the Micro-frontend Config API in edx-platform. More information on this API can be\n * found in the ADR which introduced it:\n *\n * https://github.com/openedx/edx-platform/blob/master/lms/djangoapps/mfe_config_api/docs/decisions/0001-mfe-config-api.rst\n *\n * The runtime configuration method can be enabled by supplying a MFE_CONFIG_API_URL via one of the other\n * two configuration methods above.\n *\n * Runtime configuration is particularly useful if you need to supply different configurations to\n * a single deployment of a micro-frontend, for instance. It is also a perfectly valid alternative\n * to build-time configuration, though it introduces an additional API call to edx-platform on MFE\n * initialization.\n *\n * ##### Initialization Config Handler\n *\n * The configuration document can be extended by\n * applications at run-time using a `config` initialization handler. Please see the Initialization\n * documentation for more information on handlers and initialization phases.\n *\n * ```\n * initialize({\n * handlers: {\n * config: () => {\n * mergeConfig({\n * CUSTOM_VARIABLE: 'custom value',\n * LMS_BASE_URL: 'http://localhost:18001' // You can override variables, but this is uncommon.\n * }, 'App config override handler');\n * },\n * },\n * });\n * ```\n *\n * @module Config\n */\n\nimport { APP_CONFIG_INITIALIZED, CONFIG_CHANGED } from './constants';\n\nimport { publish, subscribe } from './pubSub';\nimport { ensureDefinedConfig } from './utils';\n\nfunction extractRegex(envVar) {\n // Convert the environment variable string to a regex, while guarding\n // against a non-string and an empty/whitespace-only string.\n if (typeof envVar === 'string' && envVar.trim() !== '') {\n return new RegExp(envVar);\n }\n return undefined;\n}\n\n/**\n * Safely parses a JSON string coming from the environment variables.\n * If the JSON is invalid, the function returns an empty object and logs an error to the console.\n *\n * @param {string} paragonUrlsJson - The JSON string representing Paragon theme URLs.\n * @returns {Object|undefined} - Returns a parsed object if the JSON is valid; otherwise, returns\n * an empty object if invalid or undefined if no input is provided.\n *\n * @example\n * const jsonString = '{\n * \"core\":{\"urls\":{\"default\":\"core.min.css\"}},\n * \"defaults\":{\"light\":\"light\"},\n * \"variants\":{\"light\":{\"urls\":{\"default\":\"light.min.css\"}}}\n * }';\n * const parsedUrls = parseParagonThemeUrls(jsonString);\n * console.log(parsedUrls); // Outputs the parsed JSON object\n */\nfunction parseParagonThemeUrls(paragonUrlsJson) {\n if (!paragonUrlsJson) {\n return undefined;\n }\n try {\n return JSON.parse(paragonUrlsJson);\n } catch (err) {\n if (err instanceof SyntaxError) {\n // eslint-disable-next-line no-console\n console.error('Unable to parse PARAGON_THEME_URLS JSON.\\nPlease check https://github.com/openedx/frontend-platform/tree/master/docs/how_tos/theming.md for the expected formatting.\\nAn empty object ({}) will be returned, which will cause the theming configuration to fall back to the installed packages.');\n return {};\n }\n // In case of a different type of error, return the error object itself\n return err;\n }\n}\n\nconst ENVIRONMENT = process.env.NODE_ENV;\nlet config = {\n ACCESS_TOKEN_COOKIE_NAME: process.env.ACCESS_TOKEN_COOKIE_NAME,\n ACCOUNT_PROFILE_URL: process.env.ACCOUNT_PROFILE_URL,\n ACCOUNT_SETTINGS_URL: process.env.ACCOUNT_SETTINGS_URL,\n BASE_URL: process.env.BASE_URL,\n PUBLIC_PATH: process.env.PUBLIC_PATH || '/',\n CREDENTIALS_BASE_URL: process.env.CREDENTIALS_BASE_URL,\n CSRF_TOKEN_API_PATH: process.env.CSRF_TOKEN_API_PATH,\n DISCOVERY_API_BASE_URL: process.env.DISCOVERY_API_BASE_URL,\n PUBLISHER_BASE_URL: process.env.PUBLISHER_BASE_URL,\n ECOMMERCE_BASE_URL: process.env.ECOMMERCE_BASE_URL,\n ENVIRONMENT,\n IGNORED_ERROR_REGEX: extractRegex(process.env.IGNORED_ERROR_REGEX),\n LANGUAGE_PREFERENCE_COOKIE_NAME: process.env.LANGUAGE_PREFERENCE_COOKIE_NAME,\n LEARNING_BASE_URL: process.env.LEARNING_BASE_URL,\n LMS_BASE_URL: process.env.LMS_BASE_URL,\n LOGIN_URL: process.env.LOGIN_URL,\n LOGOUT_URL: process.env.LOGOUT_URL,\n STUDIO_BASE_URL: process.env.STUDIO_BASE_URL,\n MARKETING_SITE_BASE_URL: process.env.MARKETING_SITE_BASE_URL,\n ORDER_HISTORY_URL: process.env.ORDER_HISTORY_URL,\n REFRESH_ACCESS_TOKEN_ENDPOINT: process.env.REFRESH_ACCESS_TOKEN_ENDPOINT,\n SECURE_COOKIES: ENVIRONMENT !== 'development',\n SEGMENT_KEY: process.env.SEGMENT_KEY,\n SITE_NAME: process.env.SITE_NAME,\n USER_INFO_COOKIE_NAME: process.env.USER_INFO_COOKIE_NAME,\n LOGO_URL: process.env.LOGO_URL,\n LOGO_TRADEMARK_URL: process.env.LOGO_TRADEMARK_URL,\n LOGO_WHITE_URL: process.env.LOGO_WHITE_URL,\n FAVICON_URL: process.env.FAVICON_URL,\n MFE_CONFIG_API_URL: process.env.MFE_CONFIG_API_URL,\n APP_ID: process.env.APP_ID,\n SUPPORT_URL: process.env.SUPPORT_URL,\n PARAGON_THEME_URLS: parseParagonThemeUrls(process.env.PARAGON_THEME_URLS),\n};\n\n/**\n * Getter for the application configuration document. This is synchronous and merely returns a\n * reference to an existing object, and is thus safe to call as often as desired.\n *\n * Example:\n *\n * ```\n * import { getConfig } from '@edx/frontend-platform';\n *\n * const {\n * LMS_BASE_URL,\n * } = getConfig();\n * ```\n *\n * @returns {ConfigDocument}\n */\nexport function getConfig() {\n return config;\n}\n\n/**\n * Replaces the existing ConfigDocument. This is not commonly used, but can be helpful for tests.\n *\n * The supplied config document will be tested with `ensureDefinedConfig` to ensure it does not\n * have any `undefined` keys.\n *\n * Example:\n *\n * ```\n * import { setConfig } from '@edx/frontend-platform';\n *\n * setConfig({\n * LMS_BASE_URL, // This is overriding the ENTIRE document - this is not merged in!\n * });\n * ```\n *\n * @param {ConfigDocument} newConfig\n */\nexport function setConfig(newConfig) {\n ensureDefinedConfig(config, 'config');\n config = newConfig;\n publish(CONFIG_CHANGED);\n}\n\n/**\n * Merges additional configuration values into the ConfigDocument returned by `getConfig`. Will\n * override any values that exist with the same keys.\n *\n * ```\n * mergeConfig({\n * NEW_KEY: 'new value',\n * OTHER_NEW_KEY: 'other new value',\n * });\n *\n * If any of the key values are `undefined`, an error will be logged to 'warn'.\n *\n * @param {Object} newConfig\n */\nexport function mergeConfig(newConfig) {\n ensureDefinedConfig(newConfig, 'ProcessEnvConfigService');\n config = Object.assign(config, newConfig);\n publish(CONFIG_CHANGED);\n}\n\n/**\n * A method allowing application code to indicate that particular ConfigDocument keys are required\n * for them to function. This is useful for diagnosing development/deployment issues, primarily,\n * by surfacing misconfigurations early. For instance, if the build process fails to supply an\n * environment variable on the command-line, it's possible that one of the `process.env` variables\n * will be undefined. Should be used in conjunction with `mergeConfig` for custom `ConfigDocument`\n * properties. Requester is for informational/error reporting purposes only.\n *\n * ```\n * ensureConfig(['LMS_BASE_URL', 'LOGIN_URL'], 'MySpecialComponent');\n *\n * // Will log a warning with:\n * // \"App configuration error: LOGIN_URL is required by MySpecialComponent.\"\n * // if LOGIN_URL is undefined, for example.\n * ```\n *\n * *NOTE*: `ensureConfig` waits until `APP_CONFIG_INITIALIZED` is published to verify the existence\n * of the specified properties. This means that this function is compatible with custom `config`\n * phase handlers responsible for loading additional configuration data in the initialization\n * sequence.\n *\n * @param {Array} keys\n * @param {string} [requester='unspecified application code']\n */\nexport function ensureConfig(keys, requester = 'unspecified application code') {\n subscribe(APP_CONFIG_INITIALIZED, () => {\n keys.forEach((key) => {\n if (config[key] === undefined) {\n // eslint-disable-next-line no-console\n console.warn(`App configuration error: ${key} is required by ${requester}.`);\n }\n });\n });\n}\n\n/**\n * An object describing the current application configuration.\n *\n * In its most basic form, the initialization process loads this document via `process.env`\n * variables. There are other ways to add configuration variables to the ConfigDocument as\n * documented above (JavaScript File Configuration, Runtime Configuration, and the Initialization\n * Config Handler)\n *\n * ```\n * {\n * BASE_URL: process.env.BASE_URL,\n * // ... other vars\n * }\n * ```\n *\n * When using Webpack (i.e., normal usage), the build process is responsible for supplying these\n * variables via command-line environment variables. That means they must be supplied at build\n * time.\n *\n * @name ConfigDocument\n * @memberof module:Config\n * @property {string} ACCESS_TOKEN_COOKIE_NAME\n * @property {string} ACCOUNT_PROFILE_URL\n * @property {string} ACCOUNT_SETTINGS_URL\n * @property {string} BASE_URL The URL of the current application.\n * @property {string} CREDENTIALS_BASE_URL\n * @property {string} CSRF_TOKEN_API_PATH\n * @property {string} DISCOVERY_API_BASE_URL\n * @property {string} PUBLISHER_BASE_URL\n * @property {string} ECOMMERCE_BASE_URL\n * @property {string} ENVIRONMENT This is one of: development, production, or test.\n * @property {string} IGNORED_ERROR_REGEX\n * @property {string} LANGUAGE_PREFERENCE_COOKIE_NAME\n * @property {string} LEARNING_BASE_URL\n * @property {string} LMS_BASE_URL\n * @property {string} LOGIN_URL\n * @property {string} LOGOUT_URL\n * @property {string} STUDIO_BASE_URL\n * @property {string} MARKETING_SITE_BASE_URL\n * @property {string} ORDER_HISTORY_URL\n * @property {string} REFRESH_ACCESS_TOKEN_ENDPOINT\n * @property {boolean} SECURE_COOKIES\n * @property {string} SEGMENT_KEY\n * @property {string} SITE_NAME\n * @property {string} USER_INFO_COOKIE_NAME\n * @property {string} LOGO_URL\n * @property {string} LOGO_TRADEMARK_URL\n * @property {string} LOGO_WHITE_URL\n * @property {string} FAVICON_URL\n * @property {string} MFE_CONFIG_API_URL\n * @property {string} APP_ID\n * @property {string} SUPPORT_URL\n * @property {string} PARAGON_THEME_URLS\n */\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,SAASA,sBAAsB,EAAEC,cAAc,QAAQ,aAAa;AAEpE,SAASC,OAAO,EAAEC,SAAS,QAAQ,UAAU;AAC7C,SAASC,mBAAmB,QAAQ,SAAS;AAE7C,SAASC,YAAYA,CAACC,MAAM,EAAE;EAC5B;EACA;EACA,IAAI,OAAOA,MAAM,KAAK,QAAQ,IAAIA,MAAM,CAACC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE;IACtD,OAAO,IAAIC,MAAM,CAACF,MAAM,CAAC;EAC3B;EACA,OAAOG,SAAS;AAClB;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASC,qBAAqBA,CAACC,eAAe,EAAE;EAC9C,IAAI,CAACA,eAAe,EAAE;IACpB,OAAOF,SAAS;EAClB;EACA,IAAI;IACF,OAAOG,IAAI,CAACC,KAAK,CAACF,eAAe,CAAC;EACpC,CAAC,CAAC,OAAOG,GAAG,EAAE;IACZ,IAAIA,GAAG,YAAYC,WAAW,E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AC;AACzB;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAAS4D,YAAYA,CAACC,IAAI,EAA8C;EAAA,IAA5CC,SAAS,GAAAC,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAAvD,SAAA,GAAAuD,SAAA,MAAG,8BAA8B;EAC3E7D,SAAS,CAACH,sBAAsB,EAAE,YAAM;IACtC8D,IAAI,CAACI,OAAO,CAAC,UAACC,GAAG,EAAK;MACpB,IAAI7C,MAAM,CAAC6C,GAAG,CAAC,KAAK1D,SAAS,EAAE;QAC7B;QACAO,OAAO,CAACoD,IAAI,6BAAAC,MAAA,CAA6BF,GAAG,sBAAAE,MAAA,CAAmBN,SAAS,MAAG,CAAC;MAC9E;IACF,CAAC,CAAC;EACJ,CAAC,CAAC;AACJ;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","ignoreList":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@edx/frontend-platform",
3
- "version": "8.2.1",
3
+ "version": "8.3.0",
4
4
  "description": "Foundational application framework for Open edX micro-frontend applications.",
5
5
  "main": "index.js",
6
6
  "publishConfig": {
@@ -36,13 +36,15 @@
36
36
  "@edx/brand": "npm:@openedx/brand-openedx@^1.2.2",
37
37
  "@edx/browserslist-config": "1.5.0",
38
38
  "@openedx/frontend-build": "^14.3.0",
39
- "@openedx/paragon": "22.15.1",
39
+ "@openedx/paragon": "^23.3.0",
40
+ "@testing-library/dom": "10.4.0",
40
41
  "@testing-library/jest-dom": "6.6.3",
41
42
  "@testing-library/react": "16.2.0",
42
- "@testing-library/dom": "10.4.0",
43
+ "@testing-library/user-event": "14.4.3",
43
44
  "axios-mock-adapter": "^1.22.0",
44
45
  "husky": "8.0.3",
45
46
  "jest-environment-jsdom": "29.7.0",
47
+ "jest-localstorage-mock": "^2.4.26",
46
48
  "jsdoc": "^4.0.0",
47
49
  "nodemon": "3.1.9",
48
50
  "prop-types": "15.8.1",
@@ -75,7 +77,7 @@
75
77
  },
76
78
  "peerDependencies": {
77
79
  "@openedx/frontend-build": ">= 14.0.0",
78
- "@openedx/paragon": ">= 21.5.7 < 23.0.0",
80
+ "@openedx/paragon": ">= 21.5.7 < 24.0.0",
79
81
  "prop-types": ">=15.7.2 <16.0.0",
80
82
  "react": "^16.9.0 || ^17.0.0 || ^18.0.0",
81
83
  "react-dom": "^16.9.0 || ^17.0.0 || ^18.0.0",
@@ -10,12 +10,14 @@ import { BrowserRouter as Router } from 'react-router-dom';
10
10
  import OptionalReduxProvider from './OptionalReduxProvider';
11
11
  import ErrorBoundary from './ErrorBoundary';
12
12
  import AppContext from './AppContext';
13
- import { useAppEvent, useTrackColorSchemeChoice } from './hooks';
13
+ import { useAppEvent, useParagonTheme, useTrackColorSchemeChoice } from './hooks';
14
+ import { paragonThemeActions } from './reducers';
14
15
  import { getAuthenticatedUser, AUTHENTICATED_USER_CHANGED } from '../auth';
15
16
  import { getConfig } from '../config';
16
17
  import { CONFIG_CHANGED } from '../constants';
17
18
  import { getLocale, getMessages, IntlProvider, LOCALE_CHANGED } from '../i18n';
18
19
  import { basename } from '../initialize';
20
+ import { SELECTED_THEME_VARIANT_KEY } from './constants';
19
21
 
20
22
  /**
21
23
  * A wrapper component for React-based micro-frontends to initialize a number of common data/
@@ -38,6 +40,7 @@ import { basename } from '../initialize';
38
40
  * - Optionally a redux `Provider`. Will only be included if a `store` property is passed to
39
41
  * `AppProvider`.
40
42
  * - A `Router` for react-router.
43
+ * - A theme manager for Paragon.
41
44
  *
42
45
  * @param {Object} props
43
46
  * @param {Object} [props.store] A redux store.
@@ -61,7 +64,6 @@ export default function AppProvider(_ref) {
61
64
  _useState6 = _slicedToArray(_useState5, 2),
62
65
  locale = _useState6[0],
63
66
  setLocale = _useState6[1];
64
- useTrackColorSchemeChoice();
65
67
  useAppEvent(AUTHENTICATED_USER_CHANGED, function () {
66
68
  setAuthenticatedUser(getAuthenticatedUser());
67
69
  });
@@ -71,13 +73,30 @@ export default function AppProvider(_ref) {
71
73
  useAppEvent(LOCALE_CHANGED, function () {
72
74
  setLocale(getLocale());
73
75
  });
76
+ useTrackColorSchemeChoice();
77
+ var _useParagonTheme = useParagonTheme(),
78
+ _useParagonTheme2 = _slicedToArray(_useParagonTheme, 2),
79
+ paragonThemeState = _useParagonTheme2[0],
80
+ paragonThemeDispatch = _useParagonTheme2[1];
74
81
  var appContextValue = useMemo(function () {
75
82
  return {
76
83
  authenticatedUser: authenticatedUser,
77
84
  config: config,
78
- locale: locale
85
+ locale: locale,
86
+ paragonTheme: {
87
+ state: paragonThemeState,
88
+ setThemeVariant: function setThemeVariant(themeVariant) {
89
+ paragonThemeDispatch(paragonThemeActions.setParagonThemeVariant(themeVariant));
90
+
91
+ // Persist selected theme variant to localStorage.
92
+ window.localStorage.setItem(SELECTED_THEME_VARIANT_KEY, themeVariant);
93
+ }
94
+ }
79
95
  };
80
- }, [authenticatedUser, config, locale]);
96
+ }, [authenticatedUser, config, locale, paragonThemeState, paragonThemeDispatch]);
97
+ if (!(paragonThemeState !== null && paragonThemeState !== void 0 && paragonThemeState.isThemeLoaded)) {
98
+ return null;
99
+ }
81
100
  return /*#__PURE__*/React.createElement(IntlProvider, {
82
101
  locale: locale,
83
102
  messages: getMessages()
@@ -92,7 +111,7 @@ export default function AppProvider(_ref) {
92
111
  }, children)) : children))));
93
112
  }
94
113
  AppProvider.propTypes = {
95
- store: PropTypes.shape(),
114
+ store: PropTypes.shape({}),
96
115
  children: PropTypes.node.isRequired,
97
116
  wrapWithRouter: PropTypes.bool
98
117
  };
@@ -1 +1 @@
1
- {"version":3,"file":"AppProvider.js","names":["React","useState","useMemo","PropTypes","BrowserRouter","Router","OptionalReduxProvider","ErrorBoundary","AppContext","useAppEvent","useTrackColorSchemeChoice","getAuthenticatedUser","AUTHENTICATED_USER_CHANGED","getConfig","CONFIG_CHANGED","getLocale","getMessages","IntlProvider","LOCALE_CHANGED","basename","AppProvider","_ref","_ref$store","store","children","_ref$wrapWithRouter","wrapWithRouter","_useState","_useState2","_slicedToArray","config","setConfig","_useState3","_useState4","authenticatedUser","setAuthenticatedUser","_useState5","_useState6","locale","setLocale","appContextValue","createElement","messages","Provider","value","propTypes","shape","node","isRequired","bool"],"sources":["../../src/react/AppProvider.jsx"],"sourcesContent":["import React, { useState, useMemo } from 'react';\nimport PropTypes from 'prop-types';\nimport { BrowserRouter as Router } from 'react-router-dom';\n\nimport OptionalReduxProvider from './OptionalReduxProvider';\n\nimport ErrorBoundary from './ErrorBoundary';\nimport AppContext from './AppContext';\nimport { useAppEvent, useTrackColorSchemeChoice } from './hooks';\nimport { getAuthenticatedUser, AUTHENTICATED_USER_CHANGED } from '../auth';\nimport { getConfig } from '../config';\nimport { CONFIG_CHANGED } from '../constants';\nimport {\n getLocale,\n getMessages,\n IntlProvider,\n LOCALE_CHANGED,\n} from '../i18n';\nimport { basename } from '../initialize';\n\n/**\n * A wrapper component for React-based micro-frontends to initialize a number of common data/\n * context providers.\n *\n * ```\n * subscribe(APP_READY, () => {\n * ReactDOM.render(\n * <AppProvider>\n * <HelloWorld />\n * </AppProvider>\n * )\n * });\n * ```\n *\n * This will provide the following to HelloWorld:\n * - An error boundary as described above.\n * - An `AppContext` provider for React context data.\n * - IntlProvider for @edx/frontend-i18n internationalization\n * - Optionally a redux `Provider`. Will only be included if a `store` property is passed to\n * `AppProvider`.\n * - A `Router` for react-router.\n *\n * @param {Object} props\n * @param {Object} [props.store] A redux store.\n * @memberof module:React\n */\nexport default function AppProvider({ store = null, children, wrapWithRouter = true }) {\n const [config, setConfig] = useState(getConfig());\n const [authenticatedUser, setAuthenticatedUser] = useState(getAuthenticatedUser());\n const [locale, setLocale] = useState(getLocale());\n\n useTrackColorSchemeChoice();\n\n useAppEvent(AUTHENTICATED_USER_CHANGED, () => {\n setAuthenticatedUser(getAuthenticatedUser());\n });\n\n useAppEvent(CONFIG_CHANGED, () => {\n setConfig(getConfig());\n });\n\n useAppEvent(LOCALE_CHANGED, () => {\n setLocale(getLocale());\n });\n\n const appContextValue = useMemo(() => ({ authenticatedUser, config, locale }), [authenticatedUser, config, locale]);\n\n return (\n <IntlProvider locale={locale} messages={getMessages()}>\n <ErrorBoundary>\n <AppContext.Provider\n value={appContextValue}\n >\n <OptionalReduxProvider store={store}>\n {wrapWithRouter ? (\n <Router basename={basename}>\n <div data-testid=\"browser-router\">\n {children}\n </div>\n </Router>\n ) : children}\n </OptionalReduxProvider>\n </AppContext.Provider>\n </ErrorBoundary>\n </IntlProvider>\n );\n}\n\nAppProvider.propTypes = {\n store: PropTypes.shape(),\n children: PropTypes.node.isRequired,\n wrapWithRouter: PropTypes.bool,\n};\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"AppProvider.js","names":["React","useState","useMemo","PropTypes","BrowserRouter","Router","OptionalReduxProvider","ErrorBoundary","AppContext","useAppEvent","useParagonTheme","useTrackColorSchemeChoice","paragonThemeActions","getAuthenticatedUser","AUTHENTICATED_USER_CHANGED","getConfig","CONFIG_CHANGED","getLocale","getMessages","IntlProvider","LOCALE_CHANGED","basename","SELECTED_THEME_VARIANT_KEY","AppProvider","_ref","_ref$store","store","children","_ref$wrapWithRouter","wrapWithRouter","_useState","_useState2","_slicedToArray","config","setConfig","_useState3","_useState4","authenticatedUser","setAuthenticatedUser","_useState5","_useState6","locale","setLocale","_useParagonTheme","_useParagonTheme2","paragonThemeState","paragonThemeDispatch","appContextValue","paragonTheme","state","setThemeVariant","themeVariant","setParagonThemeVariant","window","localStorage","setItem","isThemeLoaded","createElement","messages","Provider","value","propTypes","shape","node","isRequired","bool"],"sources":["../../src/react/AppProvider.jsx"],"sourcesContent":["import React, { useState, useMemo } from 'react';\nimport PropTypes from 'prop-types';\nimport { BrowserRouter as Router } from 'react-router-dom';\n\nimport OptionalReduxProvider from './OptionalReduxProvider';\n\nimport ErrorBoundary from './ErrorBoundary';\nimport AppContext from './AppContext';\nimport {\n useAppEvent,\n useParagonTheme,\n useTrackColorSchemeChoice,\n} from './hooks';\nimport { paragonThemeActions } from './reducers';\nimport { getAuthenticatedUser, AUTHENTICATED_USER_CHANGED } from '../auth';\nimport { getConfig } from '../config';\nimport { CONFIG_CHANGED } from '../constants';\nimport {\n getLocale,\n getMessages,\n IntlProvider,\n LOCALE_CHANGED,\n} from '../i18n';\nimport { basename } from '../initialize';\nimport { SELECTED_THEME_VARIANT_KEY } from './constants';\n\n/**\n * A wrapper component for React-based micro-frontends to initialize a number of common data/\n * context providers.\n *\n * ```\n * subscribe(APP_READY, () => {\n * ReactDOM.render(\n * <AppProvider>\n * <HelloWorld />\n * </AppProvider>\n * )\n * });\n * ```\n *\n * This will provide the following to HelloWorld:\n * - An error boundary as described above.\n * - An `AppContext` provider for React context data.\n * - IntlProvider for @edx/frontend-i18n internationalization\n * - Optionally a redux `Provider`. Will only be included if a `store` property is passed to\n * `AppProvider`.\n * - A `Router` for react-router.\n * - A theme manager for Paragon.\n *\n * @param {Object} props\n * @param {Object} [props.store] A redux store.\n * @memberof module:React\n */\nexport default function AppProvider({ store = null, children, wrapWithRouter = true }) {\n const [config, setConfig] = useState(getConfig());\n const [authenticatedUser, setAuthenticatedUser] = useState(getAuthenticatedUser());\n const [locale, setLocale] = useState(getLocale());\n\n useAppEvent(AUTHENTICATED_USER_CHANGED, () => {\n setAuthenticatedUser(getAuthenticatedUser());\n });\n\n useAppEvent(CONFIG_CHANGED, () => {\n setConfig(getConfig());\n });\n\n useAppEvent(LOCALE_CHANGED, () => {\n setLocale(getLocale());\n });\n\n useTrackColorSchemeChoice();\n const [paragonThemeState, paragonThemeDispatch] = useParagonTheme();\n\n const appContextValue = useMemo(() => ({\n authenticatedUser,\n config,\n locale,\n paragonTheme: {\n state: paragonThemeState,\n setThemeVariant: (themeVariant) => {\n paragonThemeDispatch(paragonThemeActions.setParagonThemeVariant(themeVariant));\n\n // Persist selected theme variant to localStorage.\n window.localStorage.setItem(SELECTED_THEME_VARIANT_KEY, themeVariant);\n },\n },\n }), [authenticatedUser, config, locale, paragonThemeState, paragonThemeDispatch]);\n\n if (!paragonThemeState?.isThemeLoaded) {\n return null;\n }\n\n return (\n <IntlProvider locale={locale} messages={getMessages()}>\n <ErrorBoundary>\n <AppContext.Provider\n value={appContextValue}\n >\n <OptionalReduxProvider store={store}>\n {wrapWithRouter ? (\n <Router basename={basename}>\n <div data-testid=\"browser-router\">\n {children}\n </div>\n </Router>\n ) : children}\n </OptionalReduxProvider>\n </AppContext.Provider>\n </ErrorBoundary>\n </IntlProvider>\n );\n}\n\nAppProvider.propTypes = {\n store: PropTypes.shape({}),\n children: PropTypes.node.isRequired,\n wrapWithRouter: PropTypes.bool,\n};\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,4 @@
1
+ export var SET_THEME_VARIANT = 'SET_THEME_VARIANT';
2
+ export var SET_IS_THEME_LOADED = 'SET_IS_THEME_LOADED';
3
+ export var SELECTED_THEME_VARIANT_KEY = 'selected-paragon-theme-variant';
4
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","names":["SET_THEME_VARIANT","SET_IS_THEME_LOADED","SELECTED_THEME_VARIANT_KEY"],"sources":["../../src/react/constants.js"],"sourcesContent":["export const SET_THEME_VARIANT = 'SET_THEME_VARIANT';\nexport const SET_IS_THEME_LOADED = 'SET_IS_THEME_LOADED';\nexport const SELECTED_THEME_VARIANT_KEY = 'selected-paragon-theme-variant';\n"],"mappings":"AAAA,OAAO,IAAMA,iBAAiB,GAAG,mBAAmB;AACpD,OAAO,IAAMC,mBAAmB,GAAG,qBAAqB;AACxD,OAAO,IAAMC,0BAA0B,GAAG,gCAAgC","ignoreList":[]}
@@ -0,0 +1,3 @@
1
+ export { default as useAppEvent } from './useAppEvent';
2
+ export * from './paragon';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["default","useAppEvent"],"sources":["../../../src/react/hooks/index.js"],"sourcesContent":["export { default as useAppEvent } from './useAppEvent';\n\nexport * from './paragon';\n"],"mappings":"AAAA,SAASA,OAAO,IAAIC,WAAW,QAAQ,eAAe;AAEtD,cAAc,WAAW","ignoreList":[]}
@@ -0,0 +1,3 @@
1
+ export { default as useTrackColorSchemeChoice } from './useTrackColorSchemeChoice';
2
+ export { default as useParagonTheme } from './useParagonTheme';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["default","useTrackColorSchemeChoice","useParagonTheme"],"sources":["../../../../src/react/hooks/paragon/index.js"],"sourcesContent":["export { default as useTrackColorSchemeChoice } from './useTrackColorSchemeChoice';\nexport { default as useParagonTheme } from './useParagonTheme';\n"],"mappings":"AAAA,SAASA,OAAO,IAAIC,yBAAyB,QAAQ,6BAA6B;AAClF,SAASD,OAAO,IAAIE,eAAe,QAAQ,mBAAmB","ignoreList":[]}
@@ -0,0 +1,192 @@
1
+ function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
2
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
3
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
4
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
5
+ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
6
+ function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
7
+ import { useCallback, useEffect, useReducer, useState } from 'react';
8
+ import { SELECTED_THEME_VARIANT_KEY } from '../../constants';
9
+ import { logError } from '../../../logging';
10
+ import { paragonThemeActions, paragonThemeReducer } from '../../reducers';
11
+ import { isEmptyObject } from './utils';
12
+ import useParagonThemeCore from './useParagonThemeCore';
13
+ import useParagonThemeUrls from './useParagonThemeUrls';
14
+ import useParagonThemeVariants from './useParagonThemeVariants';
15
+
16
+ /**
17
+ * Finds the default theme variant from the given theme variants object. If no default theme exists, the light theme
18
+ * variant is returned as a fallback.
19
+ *
20
+ * It prioritizes:
21
+ * 1. A persisted theme variant from localStorage.
22
+ * 2. A system preference (`prefers-color-scheme`).
23
+ * 3. The configured default theme variant.
24
+ *
25
+ * @param {Object.<string, ParagonThemeVariant>|undefined} themeVariants - An object where the keys are theme variant
26
+ * names (e.g., "light", "dark") and the values are objects containing URLs for theme CSS files.
27
+ * @param {Object} [options.themeVariantDefaults={}] - An object containing default theme variant preferences.
28
+ *
29
+ * @returns {Object|undefined} The default theme variant, or `undefined` if no valid theme variant is found.
30
+ *
31
+ */
32
+ export var getDefaultThemeVariant = function getDefaultThemeVariant(_ref) {
33
+ var _window$matchMedia, _window;
34
+ var themeVariants = _ref.themeVariants,
35
+ _ref$themeVariantDefa = _ref.themeVariantDefaults,
36
+ themeVariantDefaults = _ref$themeVariantDefa === void 0 ? {} : _ref$themeVariantDefa;
37
+ if (!themeVariants) {
38
+ return undefined;
39
+ }
40
+ var themeVariantKeys = Object.keys(themeVariants);
41
+
42
+ // If there is only one theme variant, return it since it's the only one that may be used.
43
+ if (themeVariantKeys.length === 1) {
44
+ var themeVariantKey = themeVariantKeys[0];
45
+ return {
46
+ name: themeVariantKey,
47
+ metadata: themeVariants[themeVariantKey]
48
+ };
49
+ }
50
+
51
+ // Prioritize persisted localStorage theme variant preference.
52
+ var persistedSelectedParagonThemeVariant = localStorage.getItem(SELECTED_THEME_VARIANT_KEY);
53
+ if (persistedSelectedParagonThemeVariant && themeVariants[persistedSelectedParagonThemeVariant]) {
54
+ return {
55
+ name: persistedSelectedParagonThemeVariant,
56
+ metadata: themeVariants[persistedSelectedParagonThemeVariant]
57
+ };
58
+ }
59
+
60
+ // Then, detect system preference via `prefers-color-scheme` media query and use
61
+ // the default dark theme variant, if one exists.
62
+ var hasDarkSystemPreference = !!((_window$matchMedia = (_window = window).matchMedia) !== null && _window$matchMedia !== void 0 && (_window$matchMedia = _window$matchMedia.call(_window, '(prefers-color-scheme: dark)')) !== null && _window$matchMedia !== void 0 && _window$matchMedia.matches);
63
+ var defaultDarkThemeVariant = themeVariantDefaults.dark;
64
+ var darkThemeVariantMetadata = themeVariants[defaultDarkThemeVariant];
65
+ if (hasDarkSystemPreference && defaultDarkThemeVariant && darkThemeVariantMetadata) {
66
+ return {
67
+ name: defaultDarkThemeVariant,
68
+ metadata: darkThemeVariantMetadata
69
+ };
70
+ }
71
+ var defaultLightThemeVariant = themeVariantDefaults.light;
72
+ var lightThemeVariantMetadata = themeVariants[defaultLightThemeVariant];
73
+
74
+ // Handle edge case where the default light theme variant is not configured or provided.
75
+ if (!defaultLightThemeVariant || !lightThemeVariantMetadata) {
76
+ return undefined;
77
+ }
78
+
79
+ // Otherwise, fallback to using the default light theme variant as configured.
80
+ return {
81
+ name: defaultLightThemeVariant,
82
+ metadata: lightThemeVariantMetadata
83
+ };
84
+ };
85
+
86
+ /**
87
+ * A custom React hook that manages the application's theme state and injects the appropriate CSS for the theme core
88
+ * and theme variants (e.g., light and dark modes) into the HTML document. It handles dynamically loading the theme
89
+ * CSS based on the current theme variant, and ensures that the theme variant's CSS is preloaded for runtime theme
90
+ * switching.This is done using "alternate" stylesheets. That is, the browser will download the CSS for the
91
+ * non-current theme variants with a lower priority than the current one.
92
+ *
93
+ * The hook also responds to system theme preference changes (e.g., via the `prefers-color-scheme` media query),
94
+ * and can automatically switch the theme based on the system's dark mode or light mode preference.
95
+ *
96
+ * @memberof module:React
97
+ *
98
+ * @returns {Array} - An array containing:
99
+ * 1. An object representing the current theme state.
100
+ * 2. A dispatch function to mutate the app theme state (e.g., change the theme variant).
101
+ *
102
+ * * @example
103
+ * const [themeState, dispatch] = useParagonTheme();
104
+ * console.log(themeState.isThemeLoaded); // true when the theme has been successfully loaded.
105
+ *
106
+ * // Dispatch an action to change the theme variant
107
+ * dispatch(paragonThemeActions.setParagonThemeVariant('dark'));
108
+ */
109
+ var useParagonTheme = function useParagonTheme() {
110
+ var _getDefaultThemeVaria;
111
+ var paragonThemeUrls = useParagonThemeUrls();
112
+ var _ref2 = paragonThemeUrls || {},
113
+ themeCore = _ref2.core,
114
+ themeVariantDefaults = _ref2.defaults,
115
+ themeVariants = _ref2.variants;
116
+ var initialParagonThemeState = {
117
+ isThemeLoaded: false,
118
+ themeVariant: (_getDefaultThemeVaria = getDefaultThemeVariant({
119
+ themeVariants: themeVariants,
120
+ themeVariantDefaults: themeVariantDefaults
121
+ })) === null || _getDefaultThemeVaria === void 0 ? void 0 : _getDefaultThemeVaria.name
122
+ };
123
+ var _useReducer = useReducer(paragonThemeReducer, initialParagonThemeState),
124
+ _useReducer2 = _slicedToArray(_useReducer, 2),
125
+ themeState = _useReducer2[0],
126
+ dispatch = _useReducer2[1];
127
+ var _useState = useState(false),
128
+ _useState2 = _slicedToArray(_useState, 2),
129
+ isCoreThemeLoaded = _useState2[0],
130
+ setIsCoreThemeLoaded = _useState2[1];
131
+ var onLoadThemeCore = useCallback(function () {
132
+ setIsCoreThemeLoaded(true);
133
+ }, []);
134
+ var _useState3 = useState(false),
135
+ _useState4 = _slicedToArray(_useState3, 2),
136
+ hasLoadedThemeVariants = _useState4[0],
137
+ setHasLoadedThemeVariants = _useState4[1];
138
+ var onLoadThemeVariants = useCallback(function () {
139
+ setHasLoadedThemeVariants(true);
140
+ }, []);
141
+
142
+ // load the core theme CSS
143
+ useParagonThemeCore({
144
+ themeCore: themeCore,
145
+ onComplete: onLoadThemeCore
146
+ });
147
+
148
+ // respond to system preference changes with regard to `prefers-color-scheme: dark`.
149
+ var handleDarkModeSystemPreferenceChange = useCallback(function (prefersDarkMode) {
150
+ // Ignore system preference change if the theme variant is already set in localStorage.
151
+ if (localStorage.getItem(SELECTED_THEME_VARIANT_KEY)) {
152
+ return;
153
+ }
154
+ if (prefersDarkMode && themeVariantDefaults !== null && themeVariantDefaults !== void 0 && themeVariantDefaults.dark) {
155
+ dispatch(paragonThemeActions.setParagonThemeVariant(themeVariantDefaults.dark));
156
+ } else if (!prefersDarkMode && themeVariantDefaults !== null && themeVariantDefaults !== void 0 && themeVariantDefaults.light) {
157
+ dispatch(paragonThemeActions.setParagonThemeVariant(themeVariantDefaults.light));
158
+ } else {
159
+ logError("Could not set theme variant based on system preference (prefers dark mode: ".concat(prefersDarkMode, ")"), themeVariantDefaults, themeVariants);
160
+ }
161
+ }, [themeVariantDefaults, themeVariants]);
162
+
163
+ // load the theme variant(s) CSS
164
+ useParagonThemeVariants({
165
+ themeVariants: themeVariants,
166
+ onComplete: onLoadThemeVariants,
167
+ currentThemeVariant: themeState.themeVariant,
168
+ onDarkModeSystemPreferenceChange: handleDarkModeSystemPreferenceChange
169
+ });
170
+ useEffect(function () {
171
+ // theme is already loaded, do nothing
172
+ if (themeState.isThemeLoaded) {
173
+ return;
174
+ }
175
+ var hasThemeConfig = (themeCore === null || themeCore === void 0 ? void 0 : themeCore.urls) && !isEmptyObject(themeVariants);
176
+ if (!hasThemeConfig) {
177
+ // no theme URLs to load, set loading to false.
178
+ dispatch(paragonThemeActions.setParagonThemeLoaded(true));
179
+ }
180
+
181
+ // Return early if neither the core theme CSS nor any theme variant CSS is loaded.
182
+ if (!isCoreThemeLoaded || !hasLoadedThemeVariants) {
183
+ return;
184
+ }
185
+
186
+ // All application theme URLs are loaded
187
+ dispatch(paragonThemeActions.setParagonThemeLoaded(true));
188
+ }, [themeState.isThemeLoaded, isCoreThemeLoaded, hasLoadedThemeVariants, themeCore === null || themeCore === void 0 ? void 0 : themeCore.urls, themeVariants]);
189
+ return [themeState, dispatch];
190
+ };
191
+ export default useParagonTheme;
192
+ //# sourceMappingURL=useParagonTheme.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useParagonTheme.js","names":["useCallback","useEffect","useReducer","useState","SELECTED_THEME_VARIANT_KEY","logError","paragonThemeActions","paragonThemeReducer","isEmptyObject","useParagonThemeCore","useParagonThemeUrls","useParagonThemeVariants","getDefaultThemeVariant","_ref","_window$matchMedia","_window","themeVariants","_ref$themeVariantDefa","themeVariantDefaults","undefined","themeVariantKeys","Object","keys","length","themeVariantKey","name","metadata","persistedSelectedParagonThemeVariant","localStorage","getItem","hasDarkSystemPreference","window","matchMedia","call","matches","defaultDarkThemeVariant","dark","darkThemeVariantMetadata","defaultLightThemeVariant","light","lightThemeVariantMetadata","useParagonTheme","_getDefaultThemeVaria","paragonThemeUrls","_ref2","themeCore","core","defaults","variants","initialParagonThemeState","isThemeLoaded","themeVariant","_useReducer","_useReducer2","_slicedToArray","themeState","dispatch","_useState","_useState2","isCoreThemeLoaded","setIsCoreThemeLoaded","onLoadThemeCore","_useState3","_useState4","hasLoadedThemeVariants","setHasLoadedThemeVariants","onLoadThemeVariants","onComplete","handleDarkModeSystemPreferenceChange","prefersDarkMode","setParagonThemeVariant","concat","currentThemeVariant","onDarkModeSystemPreferenceChange","hasThemeConfig","urls","setParagonThemeLoaded"],"sources":["../../../../src/react/hooks/paragon/useParagonTheme.js"],"sourcesContent":["import {\n useCallback, useEffect, useReducer, useState,\n} from 'react';\n\nimport { SELECTED_THEME_VARIANT_KEY } from '../../constants';\nimport { logError } from '../../../logging';\nimport { paragonThemeActions, paragonThemeReducer } from '../../reducers';\nimport { isEmptyObject } from './utils';\n\nimport useParagonThemeCore from './useParagonThemeCore';\nimport useParagonThemeUrls from './useParagonThemeUrls';\nimport useParagonThemeVariants from './useParagonThemeVariants';\n\n/**\n* Finds the default theme variant from the given theme variants object. If no default theme exists, the light theme\n* variant is returned as a fallback.\n*\n* It prioritizes:\n* 1. A persisted theme variant from localStorage.\n* 2. A system preference (`prefers-color-scheme`).\n* 3. The configured default theme variant.\n*\n* @param {Object.<string, ParagonThemeVariant>|undefined} themeVariants - An object where the keys are theme variant\n* names (e.g., \"light\", \"dark\") and the values are objects containing URLs for theme CSS files.\n* @param {Object} [options.themeVariantDefaults={}] - An object containing default theme variant preferences.\n*\n* @returns {Object|undefined} The default theme variant, or `undefined` if no valid theme variant is found.\n*\n*/\nexport const getDefaultThemeVariant = ({ themeVariants, themeVariantDefaults = {} }) => {\n if (!themeVariants) {\n return undefined;\n }\n\n const themeVariantKeys = Object.keys(themeVariants);\n\n // If there is only one theme variant, return it since it's the only one that may be used.\n if (themeVariantKeys.length === 1) {\n const themeVariantKey = themeVariantKeys[0];\n return {\n name: themeVariantKey,\n metadata: themeVariants[themeVariantKey],\n };\n }\n\n // Prioritize persisted localStorage theme variant preference.\n const persistedSelectedParagonThemeVariant = localStorage.getItem(SELECTED_THEME_VARIANT_KEY);\n if (persistedSelectedParagonThemeVariant && themeVariants[persistedSelectedParagonThemeVariant]) {\n return {\n name: persistedSelectedParagonThemeVariant,\n metadata: themeVariants[persistedSelectedParagonThemeVariant],\n };\n }\n\n // Then, detect system preference via `prefers-color-scheme` media query and use\n // the default dark theme variant, if one exists.\n const hasDarkSystemPreference = !!window.matchMedia?.('(prefers-color-scheme: dark)')?.matches;\n const defaultDarkThemeVariant = themeVariantDefaults.dark;\n const darkThemeVariantMetadata = themeVariants[defaultDarkThemeVariant];\n\n if (hasDarkSystemPreference && defaultDarkThemeVariant && darkThemeVariantMetadata) {\n return {\n name: defaultDarkThemeVariant,\n metadata: darkThemeVariantMetadata,\n };\n }\n\n const defaultLightThemeVariant = themeVariantDefaults.light;\n const lightThemeVariantMetadata = themeVariants[defaultLightThemeVariant];\n\n // Handle edge case where the default light theme variant is not configured or provided.\n if (!defaultLightThemeVariant || !lightThemeVariantMetadata) {\n return undefined;\n }\n\n // Otherwise, fallback to using the default light theme variant as configured.\n return {\n name: defaultLightThemeVariant,\n metadata: lightThemeVariantMetadata,\n };\n};\n\n/**\n * A custom React hook that manages the application's theme state and injects the appropriate CSS for the theme core\n * and theme variants (e.g., light and dark modes) into the HTML document. It handles dynamically loading the theme\n * CSS based on the current theme variant, and ensures that the theme variant's CSS is preloaded for runtime theme\n * switching.This is done using \"alternate\" stylesheets. That is, the browser will download the CSS for the\n * non-current theme variants with a lower priority than the current one.\n *\n * The hook also responds to system theme preference changes (e.g., via the `prefers-color-scheme` media query),\n * and can automatically switch the theme based on the system's dark mode or light mode preference.\n *\n * @memberof module:React\n *\n * @returns {Array} - An array containing:\n * 1. An object representing the current theme state.\n * 2. A dispatch function to mutate the app theme state (e.g., change the theme variant).\n *\n * * @example\n * const [themeState, dispatch] = useParagonTheme();\n * console.log(themeState.isThemeLoaded); // true when the theme has been successfully loaded.\n *\n * // Dispatch an action to change the theme variant\n * dispatch(paragonThemeActions.setParagonThemeVariant('dark'));\n */\nconst useParagonTheme = () => {\n const paragonThemeUrls = useParagonThemeUrls();\n const {\n core: themeCore,\n defaults: themeVariantDefaults,\n variants: themeVariants,\n } = paragonThemeUrls || {};\n const initialParagonThemeState = {\n isThemeLoaded: false,\n themeVariant: getDefaultThemeVariant({ themeVariants, themeVariantDefaults })?.name,\n };\n const [themeState, dispatch] = useReducer(paragonThemeReducer, initialParagonThemeState);\n\n const [isCoreThemeLoaded, setIsCoreThemeLoaded] = useState(false);\n const onLoadThemeCore = useCallback(() => {\n setIsCoreThemeLoaded(true);\n }, []);\n\n const [hasLoadedThemeVariants, setHasLoadedThemeVariants] = useState(false);\n const onLoadThemeVariants = useCallback(() => {\n setHasLoadedThemeVariants(true);\n }, []);\n\n // load the core theme CSS\n useParagonThemeCore({\n themeCore,\n onComplete: onLoadThemeCore,\n });\n\n // respond to system preference changes with regard to `prefers-color-scheme: dark`.\n const handleDarkModeSystemPreferenceChange = useCallback((prefersDarkMode) => {\n // Ignore system preference change if the theme variant is already set in localStorage.\n if (localStorage.getItem(SELECTED_THEME_VARIANT_KEY)) {\n return;\n }\n\n if (prefersDarkMode && themeVariantDefaults?.dark) {\n dispatch(paragonThemeActions.setParagonThemeVariant(themeVariantDefaults.dark));\n } else if (!prefersDarkMode && themeVariantDefaults?.light) {\n dispatch(paragonThemeActions.setParagonThemeVariant(themeVariantDefaults.light));\n } else {\n logError(`Could not set theme variant based on system preference (prefers dark mode: ${prefersDarkMode})`, themeVariantDefaults, themeVariants);\n }\n }, [themeVariantDefaults, themeVariants]);\n\n // load the theme variant(s) CSS\n useParagonThemeVariants({\n themeVariants,\n onComplete: onLoadThemeVariants,\n currentThemeVariant: themeState.themeVariant,\n onDarkModeSystemPreferenceChange: handleDarkModeSystemPreferenceChange,\n });\n\n useEffect(() => {\n // theme is already loaded, do nothing\n if (themeState.isThemeLoaded) {\n return;\n }\n\n const hasThemeConfig = (themeCore?.urls && !isEmptyObject(themeVariants));\n if (!hasThemeConfig) {\n // no theme URLs to load, set loading to false.\n dispatch(paragonThemeActions.setParagonThemeLoaded(true));\n }\n\n // Return early if neither the core theme CSS nor any theme variant CSS is loaded.\n if (!isCoreThemeLoaded || !hasLoadedThemeVariants) {\n return;\n }\n\n // All application theme URLs are loaded\n dispatch(paragonThemeActions.setParagonThemeLoaded(true));\n }, [\n themeState.isThemeLoaded,\n isCoreThemeLoaded,\n hasLoadedThemeVariants,\n themeCore?.urls,\n themeVariants,\n ]);\n\n return [themeState, dispatch];\n};\n\nexport default useParagonTheme;\n"],"mappings":"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","ignoreList":[]}