pxt-core 13.2.0 → 13.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/built/cli.js +20 -10
  2. package/built/pxt.js +74 -11
  3. package/built/pxtlib.d.ts +19 -0
  4. package/built/pxtlib.js +54 -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;
@@ -165960,7 +166013,7 @@ function replaceStaticImagesInJsonBlob(cfg, staticAssetHandler) {
165960
166013
  return pxt.replaceStringsInJsonBlob(cfg, /^\.?\/static\/.+\.(png|gif|jpeg|jpg|svg|mp4|ico)$/i, staticAssetHandler);
165961
166014
  }
165962
166015
  function saveThemeJson(cfg, localDir, packaged) {
165963
- 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;
165964
166017
  cfg.appTheme.id = cfg.id;
165965
166018
  cfg.appTheme.title = cfg.title;
165966
166019
  cfg.appTheme.name = cfg.name;
@@ -165985,6 +166038,15 @@ function saveThemeJson(cfg, localDir, packaged) {
165985
166038
  targetStrings[theme.name] = theme.name;
165986
166039
  if (theme.description)
165987
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
+ }
165988
166050
  if (theme.homeScreenHero && typeof theme.homeScreenHero != "string") {
165989
166051
  const heroBannerCard = theme.homeScreenHero;
165990
166052
  if (heroBannerCard.title)
@@ -165995,7 +166057,7 @@ function saveThemeJson(cfg, localDir, packaged) {
165995
166057
  targetStrings[heroBannerCard.buttonLabel] = heroBannerCard.buttonLabel;
165996
166058
  }
165997
166059
  // add the labels for the target contributed types that appear in the block function create dialog
165998
- 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) {
165999
166061
  cfg.runtime.functionsOptions.extraFunctionEditorTypes.forEach(extraType => {
166000
166062
  if (extraType.label) {
166001
166063
  targetStrings[`{id:type}${extraType.label}`] = extraType.label;
@@ -166008,7 +166070,7 @@ function saveThemeJson(cfg, localDir, packaged) {
166008
166070
  }
166009
166071
  });
166010
166072
  }
166011
- 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") {
166012
166074
  for (const key of Object.keys(cfg.appTheme.assetEditor)) {
166013
166075
  const entry = cfg.appTheme.assetEditor[key];
166014
166076
  if (typeof entry === "object" && entry.label) {
@@ -166016,7 +166078,7 @@ function saveThemeJson(cfg, localDir, packaged) {
166016
166078
  }
166017
166079
  }
166018
166080
  }
166019
- 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) {
166020
166082
  for (const option of cfg.appTheme.pxtJsonOptions) {
166021
166083
  targetStrings[`{id:setting}${option.label}`] = option.label;
166022
166084
  }
@@ -166095,29 +166157,29 @@ ${gcards.map(gcard => `[${gcard.name}](${gcard.url})`).join(',\n')}
166095
166157
 
166096
166158
  `, { encoding: "utf8" });
166097
166159
  }
166098
- 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;
166099
166161
  for (const game of (multiplayerGames !== null && multiplayerGames !== void 0 ? multiplayerGames : [])) {
166100
166162
  if (game.title)
166101
166163
  targetStrings[`{id:game-title}${game.title}`] = game.title;
166102
166164
  if (game.subtitle)
166103
166165
  targetStrings[`{id:game-subtitle}${game.subtitle}`] = game.subtitle;
166104
166166
  }
166105
- 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;
166106
166168
  for (const game of (kioskGames !== null && kioskGames !== void 0 ? kioskGames : [])) {
166107
166169
  if (game.name)
166108
166170
  targetStrings[`{id:game-name}${game.name}`] = game.name;
166109
166171
  if (game.description)
166110
166172
  targetStrings[`{id:game-description}${game.description}`] = game.description;
166111
166173
  }
166112
- 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;
166113
166175
  for (const [extension, repoData] of Object.entries(approvedRepoLib !== null && approvedRepoLib !== void 0 ? approvedRepoLib : {})) {
166114
- 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 : [])) {
166115
166177
  targetStrings[`{id:extension-tag}${tag}`] = tag;
166116
166178
  }
166117
166179
  }
166118
- 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;
166119
166181
  for (const [extension, repoData] of Object.entries(builtinExtensionLib !== null && builtinExtensionLib !== void 0 ? builtinExtensionLib : {})) {
166120
- 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 : [])) {
166121
166183
  targetStrings[`{id:extension-tag}${tag}`] = tag;
166122
166184
  }
166123
166185
  }
@@ -166447,6 +166509,7 @@ function updateColorThemes(cfg) {
166447
166509
  id: themeData.id,
166448
166510
  name: themeData.name,
166449
166511
  weight: themeData.weight,
166512
+ defaultSimulatorTheme: themeData.defaultSimulatorTheme,
166450
166513
  monacoBaseTheme: themeData.monacoBaseTheme,
166451
166514
  colors: themeData.colors
166452
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;
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;
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;