pxt-core 13.1.15 → 13.1.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/built/cli.js +20 -10
  2. package/built/pxt.js +78 -11
  3. package/built/pxtlib.d.ts +20 -0
  4. package/built/pxtlib.js +58 -1
  5. package/built/pxtsim.d.ts +5 -1
  6. package/built/react-common/components/controls/Card.d.ts +1 -0
  7. package/built/react-common/components/controls/Modal.d.ts +1 -0
  8. package/built/react-common/components/share/Share.d.ts +2 -1
  9. package/built/react-common/components/share/ShareInfo.d.ts +2 -1
  10. package/built/react-common/components/theming/SimulatorThemePickerModal.d.ts +15 -0
  11. package/built/react-common/components/theming/ThemeCard.d.ts +2 -1
  12. package/built/react-common/components/theming/ThemePickerModal.d.ts +10 -1
  13. package/built/react-common/components/theming/simulatorThemeDefaults.d.ts +5 -0
  14. package/built/target.js +1 -1
  15. package/built/targetlight.js +1 -1
  16. package/built/web/main.js +30 -30
  17. package/built/web/multiplayer/js/{main.db72096c.js → main.d98f7e21.js} +2 -2
  18. package/built/web/pxtapp.js +1 -1
  19. package/built/web/pxtasseteditor.js +1 -1
  20. package/built/web/pxtembed.js +2 -2
  21. package/built/web/pxtlib.js +1 -1
  22. package/built/web/pxtworker.js +1 -1
  23. package/built/web/react-common-authcode.css +1 -1
  24. package/built/web/react-common-multiplayer.css +1 -1
  25. package/built/web/react-common-skillmap.css +1 -1
  26. package/built/web/rtlreact-common-authcode.css +1 -1
  27. package/built/web/rtlreact-common-multiplayer.css +1 -1
  28. package/built/web/rtlreact-common-skillmap.css +1 -1
  29. package/built/web/rtlsemantic.css +1 -1
  30. package/built/web/runnerembed.js +1 -1
  31. package/built/web/semantic.css +1 -1
  32. package/built/web/skillmap/js/main.6352b119.js +2 -0
  33. package/built/web/teachertool/js/{main.168add6b.js → main.138b6a8e.js} +2 -2
  34. package/built/web/tutorialtool/js/{main.16de6eb5.js → main.9b70fa5a.js} +2 -2
  35. package/localtypings/pxtarget.d.ts +25 -0
  36. package/localtypings/pxteditor.d.ts +11 -2
  37. package/package.json +1 -1
  38. package/react-common/components/controls/Card.tsx +3 -0
  39. package/react-common/components/controls/Modal.tsx +4 -2
  40. package/react-common/components/share/Share.tsx +4 -1
  41. package/react-common/components/share/ShareInfo.tsx +21 -4
  42. package/react-common/components/theming/SimulatorThemePickerModal.tsx +207 -0
  43. package/react-common/components/theming/ThemeCard.tsx +6 -4
  44. package/react-common/components/theming/ThemePickerModal.tsx +65 -4
  45. package/react-common/components/theming/simulatorThemeDefaults.ts +77 -0
  46. package/react-common/styles/controls/Modal.less +6 -6
  47. package/react-common/styles/theming/ThemePickerModal.less +193 -4
  48. package/theme/pxtjson.less +12 -0
  49. package/webapp/public/multiplayer.html +1 -1
  50. package/webapp/public/skillmap.html +1 -1
  51. package/webapp/public/teachertool.html +1 -1
  52. package/webapp/public/tutorialtool.html +1 -1
  53. package/built/web/skillmap/js/main.fb626575.js +0 -2
package/built/cli.js CHANGED
@@ -1732,7 +1732,7 @@ function replaceStaticImagesInJsonBlob(cfg, staticAssetHandler) {
1732
1732
  return pxt.replaceStringsInJsonBlob(cfg, /^\.?\/static\/.+\.(png|gif|jpeg|jpg|svg|mp4|ico)$/i, staticAssetHandler);
1733
1733
  }
1734
1734
  function saveThemeJson(cfg, localDir, packaged) {
1735
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
1735
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
1736
1736
  cfg.appTheme.id = cfg.id;
1737
1737
  cfg.appTheme.title = cfg.title;
1738
1738
  cfg.appTheme.name = cfg.name;
@@ -1757,6 +1757,15 @@ function saveThemeJson(cfg, localDir, packaged) {
1757
1757
  targetStrings[theme.name] = theme.name;
1758
1758
  if (theme.description)
1759
1759
  targetStrings[theme.description] = theme.description;
1760
+ for (const preset of (_b = (_a = cfg.simulator) === null || _a === void 0 ? void 0 : _a.themePresets) !== null && _b !== void 0 ? _b : []) {
1761
+ targetStrings[`{id:simulator-theme-name}${preset.name}`] = preset.name;
1762
+ }
1763
+ for (const layout of (_d = (_c = cfg.simulator) === null || _c === void 0 ? void 0 : _c.themeLayouts) !== null && _d !== void 0 ? _d : []) {
1764
+ targetStrings[`{id:simulator-layout-name}${layout.name}`] = layout.name;
1765
+ for (const field of (_e = layout.colorFields) !== null && _e !== void 0 ? _e : []) {
1766
+ targetStrings[`{id:simulator-theme-field}${field.label}`] = field.label;
1767
+ }
1768
+ }
1760
1769
  if (theme.homeScreenHero && typeof theme.homeScreenHero != "string") {
1761
1770
  const heroBannerCard = theme.homeScreenHero;
1762
1771
  if (heroBannerCard.title)
@@ -1767,7 +1776,7 @@ function saveThemeJson(cfg, localDir, packaged) {
1767
1776
  targetStrings[heroBannerCard.buttonLabel] = heroBannerCard.buttonLabel;
1768
1777
  }
1769
1778
  // add the labels for the target contributed types that appear in the block function create dialog
1770
- if ((_c = (_b = (_a = cfg.runtime) === null || _a === void 0 ? void 0 : _a.functionsOptions) === null || _b === void 0 ? void 0 : _b.extraFunctionEditorTypes) === null || _c === void 0 ? void 0 : _c.length) {
1779
+ if ((_h = (_g = (_f = cfg.runtime) === null || _f === void 0 ? void 0 : _f.functionsOptions) === null || _g === void 0 ? void 0 : _g.extraFunctionEditorTypes) === null || _h === void 0 ? void 0 : _h.length) {
1771
1780
  cfg.runtime.functionsOptions.extraFunctionEditorTypes.forEach(extraType => {
1772
1781
  if (extraType.label) {
1773
1782
  targetStrings[`{id:type}${extraType.label}`] = extraType.label;
@@ -1780,7 +1789,7 @@ function saveThemeJson(cfg, localDir, packaged) {
1780
1789
  }
1781
1790
  });
1782
1791
  }
1783
- if (typeof ((_d = cfg.appTheme) === null || _d === void 0 ? void 0 : _d.assetEditor) === "object") {
1792
+ if (typeof ((_j = cfg.appTheme) === null || _j === void 0 ? void 0 : _j.assetEditor) === "object") {
1784
1793
  for (const key of Object.keys(cfg.appTheme.assetEditor)) {
1785
1794
  const entry = cfg.appTheme.assetEditor[key];
1786
1795
  if (typeof entry === "object" && entry.label) {
@@ -1788,7 +1797,7 @@ function saveThemeJson(cfg, localDir, packaged) {
1788
1797
  }
1789
1798
  }
1790
1799
  }
1791
- if ((_f = (_e = cfg.appTheme) === null || _e === void 0 ? void 0 : _e.pxtJsonOptions) === null || _f === void 0 ? void 0 : _f.length) {
1800
+ if ((_l = (_k = cfg.appTheme) === null || _k === void 0 ? void 0 : _k.pxtJsonOptions) === null || _l === void 0 ? void 0 : _l.length) {
1792
1801
  for (const option of cfg.appTheme.pxtJsonOptions) {
1793
1802
  targetStrings[`{id:setting}${option.label}`] = option.label;
1794
1803
  }
@@ -1867,29 +1876,29 @@ ${gcards.map(gcard => `[${gcard.name}](${gcard.url})`).join(',\n')}
1867
1876
 
1868
1877
  `, { encoding: "utf8" });
1869
1878
  }
1870
- const multiplayerGames = (_g = targetConfig === null || targetConfig === void 0 ? void 0 : targetConfig.multiplayer) === null || _g === void 0 ? void 0 : _g.games;
1879
+ const multiplayerGames = (_m = targetConfig === null || targetConfig === void 0 ? void 0 : targetConfig.multiplayer) === null || _m === void 0 ? void 0 : _m.games;
1871
1880
  for (const game of (multiplayerGames !== null && multiplayerGames !== void 0 ? multiplayerGames : [])) {
1872
1881
  if (game.title)
1873
1882
  targetStrings[`{id:game-title}${game.title}`] = game.title;
1874
1883
  if (game.subtitle)
1875
1884
  targetStrings[`{id:game-subtitle}${game.subtitle}`] = game.subtitle;
1876
1885
  }
1877
- const kioskGames = (_h = targetConfig === null || targetConfig === void 0 ? void 0 : targetConfig.kiosk) === null || _h === void 0 ? void 0 : _h.games;
1886
+ const kioskGames = (_o = targetConfig === null || targetConfig === void 0 ? void 0 : targetConfig.kiosk) === null || _o === void 0 ? void 0 : _o.games;
1878
1887
  for (const game of (kioskGames !== null && kioskGames !== void 0 ? kioskGames : [])) {
1879
1888
  if (game.name)
1880
1889
  targetStrings[`{id:game-name}${game.name}`] = game.name;
1881
1890
  if (game.description)
1882
1891
  targetStrings[`{id:game-description}${game.description}`] = game.description;
1883
1892
  }
1884
- const approvedRepoLib = (_j = targetConfig === null || targetConfig === void 0 ? void 0 : targetConfig.packages) === null || _j === void 0 ? void 0 : _j.approvedRepoLib;
1893
+ const approvedRepoLib = (_p = targetConfig === null || targetConfig === void 0 ? void 0 : targetConfig.packages) === null || _p === void 0 ? void 0 : _p.approvedRepoLib;
1885
1894
  for (const [extension, repoData] of Object.entries(approvedRepoLib !== null && approvedRepoLib !== void 0 ? approvedRepoLib : {})) {
1886
- for (const tag of ((_k = repoData.tags) !== null && _k !== void 0 ? _k : [])) {
1895
+ for (const tag of ((_q = repoData.tags) !== null && _q !== void 0 ? _q : [])) {
1887
1896
  targetStrings[`{id:extension-tag}${tag}`] = tag;
1888
1897
  }
1889
1898
  }
1890
- const builtinExtensionLib = (_l = targetConfig === null || targetConfig === void 0 ? void 0 : targetConfig.packages) === null || _l === void 0 ? void 0 : _l.builtinExtensionsLib;
1899
+ const builtinExtensionLib = (_r = targetConfig === null || targetConfig === void 0 ? void 0 : targetConfig.packages) === null || _r === void 0 ? void 0 : _r.builtinExtensionsLib;
1891
1900
  for (const [extension, repoData] of Object.entries(builtinExtensionLib !== null && builtinExtensionLib !== void 0 ? builtinExtensionLib : {})) {
1892
- for (const tag of ((_m = repoData.tags) !== null && _m !== void 0 ? _m : [])) {
1901
+ for (const tag of ((_s = repoData.tags) !== null && _s !== void 0 ? _s : [])) {
1893
1902
  targetStrings[`{id:extension-tag}${tag}`] = tag;
1894
1903
  }
1895
1904
  }
@@ -2219,6 +2228,7 @@ function updateColorThemes(cfg) {
2219
2228
  id: themeData.id,
2220
2229
  name: themeData.name,
2221
2230
  weight: themeData.weight,
2231
+ defaultSimulatorTheme: themeData.defaultSimulatorTheme,
2222
2232
  monacoBaseTheme: themeData.monacoBaseTheme,
2223
2233
  colors: themeData.colors
2224
2234
  };
package/built/pxt.js CHANGED
@@ -97927,11 +97927,60 @@ var pxt;
97927
97927
  const X_PXT_TARGET = "x-pxt-target"; // header passed in auth rest calls.
97928
97928
  const INTERACTIVE_LOGIN_UNTIL = "interactive-login-until"; // hint whether to prompt user or try SSO first.
97929
97929
  let authDisabled = false;
97930
+ auth.DEFAULT_SIMULATOR_THEME_COLOR_PROPERTIES = [
97931
+ "background-color",
97932
+ "button-stroke",
97933
+ "text-color",
97934
+ "button-fill",
97935
+ "dpad-fill",
97936
+ "joystick-handle-stroke",
97937
+ ];
97938
+ auth.DEFAULT_SIMULATOR_LAYOUT = "default";
97939
+ auth.SIMULATOR_THEMES_LOCAL_STORAGE_KEY = "user-pref:simulatorThemes";
97940
+ function isSimulatorThemeColorProperty(property) {
97941
+ return property !== "layout"
97942
+ && property !== "skin"
97943
+ && /^[a-z][a-z0-9-]*$/.test(property);
97944
+ }
97945
+ auth.isSimulatorThemeColorProperty = isSimulatorThemeColorProperty;
97946
+ function isSimulatorThemeColor(value) {
97947
+ return typeof value === "string" && /^#[0-9a-f]{6}$/i.test(value);
97948
+ }
97949
+ auth.isSimulatorThemeColor = isSimulatorThemeColor;
97950
+ function isValidSimulatorTheme(theme) {
97951
+ if (!theme || typeof theme !== "object")
97952
+ return false;
97953
+ const candidate = theme;
97954
+ const colorProperties = Object.keys(candidate).filter(property => property !== "layout");
97955
+ return colorProperties.length > 0
97956
+ && colorProperties.every(property => isSimulatorThemeColorProperty(property)
97957
+ && isSimulatorThemeColor(candidate[property]))
97958
+ && typeof candidate.layout === "string"
97959
+ && !!candidate.layout;
97960
+ }
97961
+ auth.isValidSimulatorTheme = isValidSimulatorTheme;
97962
+ function simulatorThemeColorsEqual(left, right) {
97963
+ const leftProperties = Object.keys(left).filter(isSimulatorThemeColorProperty);
97964
+ const rightProperties = Object.keys(right).filter(isSimulatorThemeColorProperty);
97965
+ return leftProperties.length === rightProperties.length
97966
+ && leftProperties.every(property => left[property] === right[property]);
97967
+ }
97968
+ auth.simulatorThemeColorsEqual = simulatorThemeColorsEqual;
97969
+ function isValidSimulatorThemePreference(preference) {
97970
+ if (!preference || typeof preference !== "object")
97971
+ return false;
97972
+ const candidate = preference;
97973
+ return typeof candidate.presetId === "string"
97974
+ && !!candidate.presetId
97975
+ && isValidSimulatorTheme(candidate.theme);
97976
+ }
97977
+ auth.isValidSimulatorThemePreference = isValidSimulatorThemePreference;
97930
97978
  auth.DEFAULT_USER_PREFERENCES = () => ({
97931
97979
  language: pxt.appTarget.appTheme.defaultLocale,
97932
97980
  highContrast: false,
97933
97981
  screenReaderMode: false,
97934
97982
  colorThemeIds: {},
97983
+ simulatorThemes: {},
97935
97984
  reader: "",
97936
97985
  skillmap: { mapProgress: {}, completedTags: {} },
97937
97986
  email: false
@@ -100446,7 +100495,11 @@ var ts;
100446
100495
  stringFiles = [{ staticName: "bundled-strings.json", path: targetId + "/bundled-strings.json" }];
100447
100496
  break;
100448
100497
  case TranslationsKind.SkillMap:
100449
- stringFiles = [{ staticName: "skillmap-strings.json", path: "/skillmap-strings.json" }];
100498
+ stringFiles = [
100499
+ { staticName: "strings.json", path: "strings.json" },
100500
+ { staticName: "target-strings.json", path: targetId + "/target-strings.json" },
100501
+ { staticName: "skillmap-strings.json", path: "/skillmap-strings.json" },
100502
+ ];
100450
100503
  break;
100451
100504
  }
100452
100505
  let translations;
@@ -117338,6 +117391,10 @@ var pxt;
117338
117391
  (isControllerMode() && editorReadonly));
117339
117392
  }
117340
117393
  shell.isReadOnly = isReadOnly;
117394
+ function hideOrganizationLogos() {
117395
+ return /[?&]hidelogos=1/i.test(window.location.href);
117396
+ }
117397
+ shell.hideOrganizationLogos = hideOrganizationLogos;
117341
117398
  function isNoProject() {
117342
117399
  return noDefaultProject;
117343
117400
  }
@@ -165956,7 +166013,7 @@ function replaceStaticImagesInJsonBlob(cfg, staticAssetHandler) {
165956
166013
  return pxt.replaceStringsInJsonBlob(cfg, /^\.?\/static\/.+\.(png|gif|jpeg|jpg|svg|mp4|ico)$/i, staticAssetHandler);
165957
166014
  }
165958
166015
  function saveThemeJson(cfg, localDir, packaged) {
165959
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
166016
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
165960
166017
  cfg.appTheme.id = cfg.id;
165961
166018
  cfg.appTheme.title = cfg.title;
165962
166019
  cfg.appTheme.name = cfg.name;
@@ -165981,6 +166038,15 @@ function saveThemeJson(cfg, localDir, packaged) {
165981
166038
  targetStrings[theme.name] = theme.name;
165982
166039
  if (theme.description)
165983
166040
  targetStrings[theme.description] = theme.description;
166041
+ for (const preset of (_b = (_a = cfg.simulator) === null || _a === void 0 ? void 0 : _a.themePresets) !== null && _b !== void 0 ? _b : []) {
166042
+ targetStrings[`{id:simulator-theme-name}${preset.name}`] = preset.name;
166043
+ }
166044
+ for (const layout of (_d = (_c = cfg.simulator) === null || _c === void 0 ? void 0 : _c.themeLayouts) !== null && _d !== void 0 ? _d : []) {
166045
+ targetStrings[`{id:simulator-layout-name}${layout.name}`] = layout.name;
166046
+ for (const field of (_e = layout.colorFields) !== null && _e !== void 0 ? _e : []) {
166047
+ targetStrings[`{id:simulator-theme-field}${field.label}`] = field.label;
166048
+ }
166049
+ }
165984
166050
  if (theme.homeScreenHero && typeof theme.homeScreenHero != "string") {
165985
166051
  const heroBannerCard = theme.homeScreenHero;
165986
166052
  if (heroBannerCard.title)
@@ -165991,7 +166057,7 @@ function saveThemeJson(cfg, localDir, packaged) {
165991
166057
  targetStrings[heroBannerCard.buttonLabel] = heroBannerCard.buttonLabel;
165992
166058
  }
165993
166059
  // add the labels for the target contributed types that appear in the block function create dialog
165994
- if ((_c = (_b = (_a = cfg.runtime) === null || _a === void 0 ? void 0 : _a.functionsOptions) === null || _b === void 0 ? void 0 : _b.extraFunctionEditorTypes) === null || _c === void 0 ? void 0 : _c.length) {
166060
+ if ((_h = (_g = (_f = cfg.runtime) === null || _f === void 0 ? void 0 : _f.functionsOptions) === null || _g === void 0 ? void 0 : _g.extraFunctionEditorTypes) === null || _h === void 0 ? void 0 : _h.length) {
165995
166061
  cfg.runtime.functionsOptions.extraFunctionEditorTypes.forEach(extraType => {
165996
166062
  if (extraType.label) {
165997
166063
  targetStrings[`{id:type}${extraType.label}`] = extraType.label;
@@ -166004,7 +166070,7 @@ function saveThemeJson(cfg, localDir, packaged) {
166004
166070
  }
166005
166071
  });
166006
166072
  }
166007
- if (typeof ((_d = cfg.appTheme) === null || _d === void 0 ? void 0 : _d.assetEditor) === "object") {
166073
+ if (typeof ((_j = cfg.appTheme) === null || _j === void 0 ? void 0 : _j.assetEditor) === "object") {
166008
166074
  for (const key of Object.keys(cfg.appTheme.assetEditor)) {
166009
166075
  const entry = cfg.appTheme.assetEditor[key];
166010
166076
  if (typeof entry === "object" && entry.label) {
@@ -166012,7 +166078,7 @@ function saveThemeJson(cfg, localDir, packaged) {
166012
166078
  }
166013
166079
  }
166014
166080
  }
166015
- if ((_f = (_e = cfg.appTheme) === null || _e === void 0 ? void 0 : _e.pxtJsonOptions) === null || _f === void 0 ? void 0 : _f.length) {
166081
+ if ((_l = (_k = cfg.appTheme) === null || _k === void 0 ? void 0 : _k.pxtJsonOptions) === null || _l === void 0 ? void 0 : _l.length) {
166016
166082
  for (const option of cfg.appTheme.pxtJsonOptions) {
166017
166083
  targetStrings[`{id:setting}${option.label}`] = option.label;
166018
166084
  }
@@ -166091,29 +166157,29 @@ ${gcards.map(gcard => `[${gcard.name}](${gcard.url})`).join(',\n')}
166091
166157
 
166092
166158
  `, { encoding: "utf8" });
166093
166159
  }
166094
- const multiplayerGames = (_g = targetConfig === null || targetConfig === void 0 ? void 0 : targetConfig.multiplayer) === null || _g === void 0 ? void 0 : _g.games;
166160
+ const multiplayerGames = (_m = targetConfig === null || targetConfig === void 0 ? void 0 : targetConfig.multiplayer) === null || _m === void 0 ? void 0 : _m.games;
166095
166161
  for (const game of (multiplayerGames !== null && multiplayerGames !== void 0 ? multiplayerGames : [])) {
166096
166162
  if (game.title)
166097
166163
  targetStrings[`{id:game-title}${game.title}`] = game.title;
166098
166164
  if (game.subtitle)
166099
166165
  targetStrings[`{id:game-subtitle}${game.subtitle}`] = game.subtitle;
166100
166166
  }
166101
- const kioskGames = (_h = targetConfig === null || targetConfig === void 0 ? void 0 : targetConfig.kiosk) === null || _h === void 0 ? void 0 : _h.games;
166167
+ const kioskGames = (_o = targetConfig === null || targetConfig === void 0 ? void 0 : targetConfig.kiosk) === null || _o === void 0 ? void 0 : _o.games;
166102
166168
  for (const game of (kioskGames !== null && kioskGames !== void 0 ? kioskGames : [])) {
166103
166169
  if (game.name)
166104
166170
  targetStrings[`{id:game-name}${game.name}`] = game.name;
166105
166171
  if (game.description)
166106
166172
  targetStrings[`{id:game-description}${game.description}`] = game.description;
166107
166173
  }
166108
- const approvedRepoLib = (_j = targetConfig === null || targetConfig === void 0 ? void 0 : targetConfig.packages) === null || _j === void 0 ? void 0 : _j.approvedRepoLib;
166174
+ const approvedRepoLib = (_p = targetConfig === null || targetConfig === void 0 ? void 0 : targetConfig.packages) === null || _p === void 0 ? void 0 : _p.approvedRepoLib;
166109
166175
  for (const [extension, repoData] of Object.entries(approvedRepoLib !== null && approvedRepoLib !== void 0 ? approvedRepoLib : {})) {
166110
- for (const tag of ((_k = repoData.tags) !== null && _k !== void 0 ? _k : [])) {
166176
+ for (const tag of ((_q = repoData.tags) !== null && _q !== void 0 ? _q : [])) {
166111
166177
  targetStrings[`{id:extension-tag}${tag}`] = tag;
166112
166178
  }
166113
166179
  }
166114
- const builtinExtensionLib = (_l = targetConfig === null || targetConfig === void 0 ? void 0 : targetConfig.packages) === null || _l === void 0 ? void 0 : _l.builtinExtensionsLib;
166180
+ const builtinExtensionLib = (_r = targetConfig === null || targetConfig === void 0 ? void 0 : targetConfig.packages) === null || _r === void 0 ? void 0 : _r.builtinExtensionsLib;
166115
166181
  for (const [extension, repoData] of Object.entries(builtinExtensionLib !== null && builtinExtensionLib !== void 0 ? builtinExtensionLib : {})) {
166116
- for (const tag of ((_m = repoData.tags) !== null && _m !== void 0 ? _m : [])) {
166182
+ for (const tag of ((_s = repoData.tags) !== null && _s !== void 0 ? _s : [])) {
166117
166183
  targetStrings[`{id:extension-tag}${tag}`] = tag;
166118
166184
  }
166119
166185
  }
@@ -166443,6 +166509,7 @@ function updateColorThemes(cfg) {
166443
166509
  id: themeData.id,
166444
166510
  name: themeData.name,
166445
166511
  weight: themeData.weight,
166512
+ defaultSimulatorTheme: themeData.defaultSimulatorTheme,
166446
166513
  monacoBaseTheme: themeData.monacoBaseTheme,
166447
166514
  colors: themeData.colors
166448
166515
  };
package/built/pxtlib.d.ts CHANGED
@@ -71,6 +71,24 @@ declare namespace pxt.auth {
71
71
  type ColorThemeIdsState = {
72
72
  [targetId: string]: string;
73
73
  };
74
+ const DEFAULT_SIMULATOR_THEME_COLOR_PROPERTIES: readonly ["background-color", "button-stroke", "text-color", "button-fill", "dpad-fill", "joystick-handle-stroke"];
75
+ const DEFAULT_SIMULATOR_LAYOUT = "default";
76
+ type SimulatorTheme = Map<string> & {
77
+ layout: string;
78
+ };
79
+ type SimulatorThemePreference = {
80
+ presetId: string;
81
+ theme: SimulatorTheme;
82
+ };
83
+ type SimulatorThemesState = {
84
+ [targetId: string]: SimulatorThemePreference;
85
+ };
86
+ const SIMULATOR_THEMES_LOCAL_STORAGE_KEY = "user-pref:simulatorThemes";
87
+ function isSimulatorThemeColorProperty(property: string): boolean;
88
+ function isSimulatorThemeColor(value: unknown): value is string;
89
+ function isValidSimulatorTheme(theme: unknown): theme is SimulatorTheme;
90
+ function simulatorThemeColorsEqual(left: Map<string>, right: Map<string>): boolean;
91
+ function isValidSimulatorThemePreference(preference: unknown): preference is SimulatorThemePreference;
74
92
  type SetPrefResult = {
75
93
  success: boolean;
76
94
  res: UserPreferences;
@@ -83,6 +101,7 @@ declare namespace pxt.auth {
83
101
  highContrast?: boolean;
84
102
  screenReaderMode?: boolean;
85
103
  colorThemeIds?: ColorThemeIdsState;
104
+ simulatorThemes?: SimulatorThemesState;
86
105
  reader?: string;
87
106
  skillmap?: UserSkillmapState;
88
107
  badges?: UserBadgeState;
@@ -2641,6 +2660,7 @@ declare namespace pxt.shell {
2641
2660
  function isSandboxMode(): boolean;
2642
2661
  function isTimeMachineEmbed(): boolean;
2643
2662
  function isReadOnly(): boolean;
2663
+ function hideOrganizationLogos(): boolean;
2644
2664
  function isNoProject(): boolean;
2645
2665
  function isControllerMode(): boolean;
2646
2666
  function getControllerMode(): ControllerMode;
package/built/pxtlib.js CHANGED
@@ -206,11 +206,60 @@ var pxt;
206
206
  const X_PXT_TARGET = "x-pxt-target"; // header passed in auth rest calls.
207
207
  const INTERACTIVE_LOGIN_UNTIL = "interactive-login-until"; // hint whether to prompt user or try SSO first.
208
208
  let authDisabled = false;
209
+ auth.DEFAULT_SIMULATOR_THEME_COLOR_PROPERTIES = [
210
+ "background-color",
211
+ "button-stroke",
212
+ "text-color",
213
+ "button-fill",
214
+ "dpad-fill",
215
+ "joystick-handle-stroke",
216
+ ];
217
+ auth.DEFAULT_SIMULATOR_LAYOUT = "default";
218
+ auth.SIMULATOR_THEMES_LOCAL_STORAGE_KEY = "user-pref:simulatorThemes";
219
+ function isSimulatorThemeColorProperty(property) {
220
+ return property !== "layout"
221
+ && property !== "skin"
222
+ && /^[a-z][a-z0-9-]*$/.test(property);
223
+ }
224
+ auth.isSimulatorThemeColorProperty = isSimulatorThemeColorProperty;
225
+ function isSimulatorThemeColor(value) {
226
+ return typeof value === "string" && /^#[0-9a-f]{6}$/i.test(value);
227
+ }
228
+ auth.isSimulatorThemeColor = isSimulatorThemeColor;
229
+ function isValidSimulatorTheme(theme) {
230
+ if (!theme || typeof theme !== "object")
231
+ return false;
232
+ const candidate = theme;
233
+ const colorProperties = Object.keys(candidate).filter(property => property !== "layout");
234
+ return colorProperties.length > 0
235
+ && colorProperties.every(property => isSimulatorThemeColorProperty(property)
236
+ && isSimulatorThemeColor(candidate[property]))
237
+ && typeof candidate.layout === "string"
238
+ && !!candidate.layout;
239
+ }
240
+ auth.isValidSimulatorTheme = isValidSimulatorTheme;
241
+ function simulatorThemeColorsEqual(left, right) {
242
+ const leftProperties = Object.keys(left).filter(isSimulatorThemeColorProperty);
243
+ const rightProperties = Object.keys(right).filter(isSimulatorThemeColorProperty);
244
+ return leftProperties.length === rightProperties.length
245
+ && leftProperties.every(property => left[property] === right[property]);
246
+ }
247
+ auth.simulatorThemeColorsEqual = simulatorThemeColorsEqual;
248
+ function isValidSimulatorThemePreference(preference) {
249
+ if (!preference || typeof preference !== "object")
250
+ return false;
251
+ const candidate = preference;
252
+ return typeof candidate.presetId === "string"
253
+ && !!candidate.presetId
254
+ && isValidSimulatorTheme(candidate.theme);
255
+ }
256
+ auth.isValidSimulatorThemePreference = isValidSimulatorThemePreference;
209
257
  auth.DEFAULT_USER_PREFERENCES = () => ({
210
258
  language: pxt.appTarget.appTheme.defaultLocale,
211
259
  highContrast: false,
212
260
  screenReaderMode: false,
213
261
  colorThemeIds: {},
262
+ simulatorThemes: {},
214
263
  reader: "",
215
264
  skillmap: { mapProgress: {}, completedTags: {} },
216
265
  email: false
@@ -2725,7 +2774,11 @@ var ts;
2725
2774
  stringFiles = [{ staticName: "bundled-strings.json", path: targetId + "/bundled-strings.json" }];
2726
2775
  break;
2727
2776
  case TranslationsKind.SkillMap:
2728
- stringFiles = [{ staticName: "skillmap-strings.json", path: "/skillmap-strings.json" }];
2777
+ stringFiles = [
2778
+ { staticName: "strings.json", path: "strings.json" },
2779
+ { staticName: "target-strings.json", path: targetId + "/target-strings.json" },
2780
+ { staticName: "skillmap-strings.json", path: "/skillmap-strings.json" },
2781
+ ];
2729
2782
  break;
2730
2783
  }
2731
2784
  let translations;
@@ -19617,6 +19670,10 @@ var pxt;
19617
19670
  (isControllerMode() && editorReadonly));
19618
19671
  }
19619
19672
  shell.isReadOnly = isReadOnly;
19673
+ function hideOrganizationLogos() {
19674
+ return /[?&]hidelogos=1/i.test(window.location.href);
19675
+ }
19676
+ shell.hideOrganizationLogos = hideOrganizationLogos;
19620
19677
  function isNoProject() {
19621
19678
  return noDefaultProject;
19622
19679
  }
package/built/pxtsim.d.ts CHANGED
@@ -562,9 +562,13 @@ declare namespace pxsim {
562
562
  }
563
563
  interface SetSimThemeMessage extends SimulatorMessage {
564
564
  type: "setsimthemecolor";
565
- part: "background-color" | "button-stroke" | "text-color" | "button-fill" | "dpad-fill";
565
+ part: string;
566
566
  color: string;
567
567
  }
568
+ interface SetSimulatorThemeMessage extends SimulatorMessage {
569
+ type: "setsimtheme";
570
+ theme: string | pxt.Map<string>;
571
+ }
568
572
  interface SetMuteButtonStateMessage extends SimulatorMessage {
569
573
  type: "setmutebuttonstate";
570
574
  state: "muted" | "unmuted" | "disabled";
@@ -4,6 +4,7 @@ export interface CardProps extends ContainerProps {
4
4
  onClick?: () => void;
5
5
  tabIndex?: number;
6
6
  ariaLabelledBy?: string;
7
+ ariaPressed?: boolean;
7
8
  label?: React.ReactNode;
8
9
  labelClass?: string;
9
10
  }
@@ -13,6 +13,7 @@ export interface ModalAction {
13
13
  }
14
14
  export interface ModalProps extends ContainerProps {
15
15
  title: string;
16
+ hideTitle?: boolean;
16
17
  leftIcon?: string;
17
18
  ariaDescribedBy?: string;
18
19
  actions?: ModalAction[];
@@ -19,10 +19,11 @@ export interface ShareProps {
19
19
  hasProjectBeenPersistentShared?: boolean;
20
20
  anonymousShareByDefault?: boolean;
21
21
  isMultiplayerGame?: boolean;
22
+ simulatorTheme?: pxt.SimulatorTheme;
22
23
  kind?: "multiplayer" | "vscode" | "share";
23
24
  setAnonymousSharePreference?: (anonymousByDefault: boolean) => void;
24
25
  simRecorder: SimRecorder;
25
- publishAsync: (name: string, description?: string, screenshotUri?: string, forceAnonymous?: boolean) => Promise<ShareData>;
26
+ publishAsync: (name: string, description?: string, screenshotUri?: string, forceAnonymous?: boolean, simulatorTheme?: pxt.SimulatorTheme) => Promise<ShareData>;
26
27
  onClose: () => void;
27
28
  }
28
29
  export declare const Share: (props: ShareProps) => JSX.Element;
@@ -7,8 +7,9 @@ export interface ShareInfoProps {
7
7
  isLoggedIn?: boolean;
8
8
  hasProjectBeenPersistentShared?: boolean;
9
9
  simRecorder: SimRecorder;
10
- publishAsync: (name: string, description?: string, screenshotUri?: string, forceAnonymous?: boolean) => Promise<ShareData>;
10
+ publishAsync: (name: string, description?: string, screenshotUri?: string, forceAnonymous?: boolean, simulatorTheme?: pxt.SimulatorTheme) => Promise<ShareData>;
11
11
  isMultiplayerGame?: boolean;
12
+ simulatorTheme?: pxt.SimulatorTheme;
12
13
  kind?: "multiplayer" | "vscode" | "share";
13
14
  anonymousShareByDefault?: boolean;
14
15
  setAnonymousSharePreference?: (anonymousByDefault: boolean) => void;
@@ -0,0 +1,15 @@
1
+ import * as React from "react";
2
+ export interface SimulatorThemePickerModalProps {
3
+ presets: pxt.SimulatorThemePreset[];
4
+ layouts?: pxt.SimulatorThemeLayout[];
5
+ initialPreference?: pxt.auth.SimulatorThemePreference;
6
+ defaultTheme?: pxt.SimulatorTheme;
7
+ accountTheme?: pxt.SimulatorTheme;
8
+ renderPreview: (theme: pxt.SimulatorTheme) => React.ReactNode;
9
+ onEditorThemeClicked?: () => void;
10
+ onUseAccountTheme?: () => void | Promise<void>;
11
+ onThemeChanged?: (preference: pxt.auth.SimulatorThemePreference) => void;
12
+ onSave: (preference: pxt.auth.SimulatorThemePreference) => void | Promise<void>;
13
+ onClose: () => void;
14
+ }
15
+ export declare const SimulatorThemePickerModal: (props: SimulatorThemePickerModalProps) => JSX.Element;
@@ -1,6 +1,7 @@
1
1
  interface ThemeCardProps {
2
2
  theme: pxt.ColorThemeInfo;
3
- onClick?: (theme: pxt.ColorThemeInfo) => void;
3
+ selected: boolean;
4
+ onClick: (theme: pxt.ColorThemeInfo) => void;
4
5
  }
5
6
  export declare const ThemeCard: (props: ThemeCardProps) => JSX.Element;
6
7
  export {};
@@ -1,6 +1,15 @@
1
+ export declare type ThemePickerMode = "editor" | "simulator";
2
+ export interface ThemePickerToggleProps {
3
+ selected: ThemePickerMode;
4
+ onModeChanged: (mode: ThemePickerMode) => void;
5
+ }
6
+ export declare const ThemePickerToggle: (props: ThemePickerToggleProps) => JSX.Element;
1
7
  export interface ThemePickerModalProps {
2
8
  themes: pxt.ColorThemeInfo[];
3
- onThemeClicked(them: pxt.ColorThemeInfo): void;
9
+ selectedThemeId?: string;
10
+ onThemeChanged: (theme: pxt.ColorThemeInfo) => void;
11
+ onSave: (theme: pxt.ColorThemeInfo) => void;
12
+ onSimulatorThemeClicked?: () => void;
4
13
  onClose(): void;
5
14
  }
6
15
  export declare const ThemePickerModal: (props: ThemePickerModalProps) => JSX.Element;
@@ -0,0 +1,5 @@
1
+ export declare function getSimulatorThemePreferenceForColorThemeChange(preference: pxt.auth.SimulatorThemePreference | undefined, previousColorTheme: pxt.ColorThemeInfo | undefined, nextColorTheme: pxt.ColorThemeInfo | undefined, presets: pxt.SimulatorThemePreset[] | undefined): pxt.auth.SimulatorThemePreference | undefined;
2
+ export declare function getDefaultSimulatorThemePreference(colorTheme: pxt.ColorThemeInfo | undefined, presets: pxt.SimulatorThemePreset[] | undefined): pxt.auth.SimulatorThemePreference | undefined;
3
+ export declare function isImplicitSimulatorThemePreference(preference: pxt.auth.SimulatorThemePreference, presets: pxt.SimulatorThemePreset[] | undefined): boolean;
4
+ export declare function copySimulatorTheme(theme: pxt.SimulatorTheme): pxt.SimulatorTheme;
5
+ export declare function getSimulatorThemeForLayout(theme: pxt.SimulatorTheme, layoutId: string, colorFields?: pxt.SimulatorThemeColorField[]): pxt.SimulatorTheme;