normalizeScreens.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. /**
  2. * @typedef {object} ScreenValue
  3. * @property {number|undefined} min
  4. * @property {number|undefined} max
  5. * @property {string|undefined} raw
  6. */ /**
  7. * @typedef {object} Screen
  8. * @property {string} name
  9. * @property {boolean} not
  10. * @property {ScreenValue[]} values
  11. */ /**
  12. * A function that normalizes the various forms that the screens object can be
  13. * provided in.
  14. *
  15. * Input(s):
  16. * - ['100px', '200px'] // Raw strings
  17. * - { sm: '100px', md: '200px' } // Object with string values
  18. * - { sm: { min: '100px' }, md: { max: '100px' } } // Object with object values
  19. * - { sm: [{ min: '100px' }, { max: '200px' }] } // Object with object array (multiple values)
  20. *
  21. * Output(s):
  22. * - [{ name: 'sm', values: [{ min: '100px', max: '200px' }] }] // List of objects, that contains multiple values
  23. *
  24. * @returns {Screen[]}
  25. */ "use strict";
  26. Object.defineProperty(exports, "__esModule", {
  27. value: true
  28. });
  29. function _export(target, all) {
  30. for(var name in all)Object.defineProperty(target, name, {
  31. enumerable: true,
  32. get: all[name]
  33. });
  34. }
  35. _export(exports, {
  36. normalizeScreens: function() {
  37. return normalizeScreens;
  38. },
  39. isScreenSortable: function() {
  40. return isScreenSortable;
  41. },
  42. compareScreens: function() {
  43. return compareScreens;
  44. },
  45. toScreen: function() {
  46. return toScreen;
  47. }
  48. });
  49. function normalizeScreens(screens, root = true) {
  50. if (Array.isArray(screens)) {
  51. return screens.map((screen)=>{
  52. if (root && Array.isArray(screen)) {
  53. throw new Error("The tuple syntax is not supported for `screens`.");
  54. }
  55. if (typeof screen === "string") {
  56. return {
  57. name: screen.toString(),
  58. not: false,
  59. values: [
  60. {
  61. min: screen,
  62. max: undefined
  63. }
  64. ]
  65. };
  66. }
  67. let [name, options] = screen;
  68. name = name.toString();
  69. if (typeof options === "string") {
  70. return {
  71. name,
  72. not: false,
  73. values: [
  74. {
  75. min: options,
  76. max: undefined
  77. }
  78. ]
  79. };
  80. }
  81. if (Array.isArray(options)) {
  82. return {
  83. name,
  84. not: false,
  85. values: options.map((option)=>resolveValue(option))
  86. };
  87. }
  88. return {
  89. name,
  90. not: false,
  91. values: [
  92. resolveValue(options)
  93. ]
  94. };
  95. });
  96. }
  97. return normalizeScreens(Object.entries(screens !== null && screens !== void 0 ? screens : {}), false);
  98. }
  99. function isScreenSortable(screen) {
  100. if (screen.values.length !== 1) {
  101. return {
  102. result: false,
  103. reason: "multiple-values"
  104. };
  105. } else if (screen.values[0].raw !== undefined) {
  106. return {
  107. result: false,
  108. reason: "raw-values"
  109. };
  110. } else if (screen.values[0].min !== undefined && screen.values[0].max !== undefined) {
  111. return {
  112. result: false,
  113. reason: "min-and-max"
  114. };
  115. }
  116. return {
  117. result: true,
  118. reason: null
  119. };
  120. }
  121. function compareScreens(type, a, z) {
  122. let aScreen = toScreen(a, type);
  123. let zScreen = toScreen(z, type);
  124. let aSorting = isScreenSortable(aScreen);
  125. let bSorting = isScreenSortable(zScreen);
  126. // These cases should never happen and indicate a bug in Tailwind CSS itself
  127. if (aSorting.reason === "multiple-values" || bSorting.reason === "multiple-values") {
  128. throw new Error("Attempted to sort a screen with multiple values. This should never happen. Please open a bug report.");
  129. } else if (aSorting.reason === "raw-values" || bSorting.reason === "raw-values") {
  130. throw new Error("Attempted to sort a screen with raw values. This should never happen. Please open a bug report.");
  131. } else if (aSorting.reason === "min-and-max" || bSorting.reason === "min-and-max") {
  132. throw new Error("Attempted to sort a screen with both min and max values. This should never happen. Please open a bug report.");
  133. }
  134. // Let the sorting begin
  135. let { min: aMin , max: aMax } = aScreen.values[0];
  136. let { min: zMin , max: zMax } = zScreen.values[0];
  137. // Negating screens flip their behavior. Basically `not min-width` is `max-width`
  138. if (a.not) [aMin, aMax] = [
  139. aMax,
  140. aMin
  141. ];
  142. if (z.not) [zMin, zMax] = [
  143. zMax,
  144. zMin
  145. ];
  146. aMin = aMin === undefined ? aMin : parseFloat(aMin);
  147. aMax = aMax === undefined ? aMax : parseFloat(aMax);
  148. zMin = zMin === undefined ? zMin : parseFloat(zMin);
  149. zMax = zMax === undefined ? zMax : parseFloat(zMax);
  150. let [aValue, zValue] = type === "min" ? [
  151. aMin,
  152. zMin
  153. ] : [
  154. zMax,
  155. aMax
  156. ];
  157. return aValue - zValue;
  158. }
  159. function toScreen(value, type) {
  160. if (typeof value === "object") {
  161. return value;
  162. }
  163. return {
  164. name: "arbitrary-screen",
  165. values: [
  166. {
  167. [type]: value
  168. }
  169. ]
  170. };
  171. }
  172. function resolveValue({ "min-width": _minWidth , min =_minWidth , max , raw } = {}) {
  173. return {
  174. min,
  175. max,
  176. raw
  177. };
  178. }