normalizeScreens.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  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: ()=>normalizeScreens,
  37. isScreenSortable: ()=>isScreenSortable,
  38. compareScreens: ()=>compareScreens,
  39. toScreen: ()=>toScreen
  40. });
  41. function normalizeScreens(screens, root = true) {
  42. if (Array.isArray(screens)) {
  43. return screens.map((screen)=>{
  44. if (root && Array.isArray(screen)) {
  45. throw new Error("The tuple syntax is not supported for `screens`.");
  46. }
  47. if (typeof screen === "string") {
  48. return {
  49. name: screen.toString(),
  50. not: false,
  51. values: [
  52. {
  53. min: screen,
  54. max: undefined
  55. }
  56. ]
  57. };
  58. }
  59. let [name, options] = screen;
  60. name = name.toString();
  61. if (typeof options === "string") {
  62. return {
  63. name,
  64. not: false,
  65. values: [
  66. {
  67. min: options,
  68. max: undefined
  69. }
  70. ]
  71. };
  72. }
  73. if (Array.isArray(options)) {
  74. return {
  75. name,
  76. not: false,
  77. values: options.map((option)=>resolveValue(option))
  78. };
  79. }
  80. return {
  81. name,
  82. not: false,
  83. values: [
  84. resolveValue(options)
  85. ]
  86. };
  87. });
  88. }
  89. return normalizeScreens(Object.entries(screens !== null && screens !== void 0 ? screens : {}), false);
  90. }
  91. function isScreenSortable(screen) {
  92. if (screen.values.length !== 1) {
  93. return {
  94. result: false,
  95. reason: "multiple-values"
  96. };
  97. } else if (screen.values[0].raw !== undefined) {
  98. return {
  99. result: false,
  100. reason: "raw-values"
  101. };
  102. } else if (screen.values[0].min !== undefined && screen.values[0].max !== undefined) {
  103. return {
  104. result: false,
  105. reason: "min-and-max"
  106. };
  107. }
  108. return {
  109. result: true,
  110. reason: null
  111. };
  112. }
  113. function compareScreens(type, a, z) {
  114. let aScreen = toScreen(a, type);
  115. let zScreen = toScreen(z, type);
  116. let aSorting = isScreenSortable(aScreen);
  117. let bSorting = isScreenSortable(zScreen);
  118. // These cases should never happen and indicate a bug in Tailwind CSS itself
  119. if (aSorting.reason === "multiple-values" || bSorting.reason === "multiple-values") {
  120. throw new Error("Attempted to sort a screen with multiple values. This should never happen. Please open a bug report.");
  121. } else if (aSorting.reason === "raw-values" || bSorting.reason === "raw-values") {
  122. throw new Error("Attempted to sort a screen with raw values. This should never happen. Please open a bug report.");
  123. } else if (aSorting.reason === "min-and-max" || bSorting.reason === "min-and-max") {
  124. throw new Error("Attempted to sort a screen with both min and max values. This should never happen. Please open a bug report.");
  125. }
  126. // Let the sorting begin
  127. let { min: aMin , max: aMax } = aScreen.values[0];
  128. let { min: zMin , max: zMax } = zScreen.values[0];
  129. // Negating screens flip their behavior. Basically `not min-width` is `max-width`
  130. if (a.not) [aMin, aMax] = [
  131. aMax,
  132. aMin
  133. ];
  134. if (z.not) [zMin, zMax] = [
  135. zMax,
  136. zMin
  137. ];
  138. aMin = aMin === undefined ? aMin : parseFloat(aMin);
  139. aMax = aMax === undefined ? aMax : parseFloat(aMax);
  140. zMin = zMin === undefined ? zMin : parseFloat(zMin);
  141. zMax = zMax === undefined ? zMax : parseFloat(zMax);
  142. let [aValue, zValue] = type === "min" ? [
  143. aMin,
  144. zMin
  145. ] : [
  146. zMax,
  147. aMax
  148. ];
  149. return aValue - zValue;
  150. }
  151. function toScreen(value, type) {
  152. if (typeof value === "object") {
  153. return value;
  154. }
  155. return {
  156. name: "arbitrary-screen",
  157. values: [
  158. {
  159. [type]: value
  160. }
  161. ]
  162. };
  163. }
  164. function resolveValue({ "min-width": _minWidth , min =_minWidth , max , raw } = {}) {
  165. return {
  166. min,
  167. max,
  168. raw
  169. };
  170. }