@kizmann/pico-js 1.0.13 → 2.0.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.
Files changed (125) hide show
  1. package/README.md +27 -7
  2. package/dist/pico-js.browser.js +2 -0
  3. package/dist/pico-js.browser.js.map +1 -0
  4. package/dist/pico-js.esm.js +2 -0
  5. package/dist/pico-js.esm.js.map +1 -0
  6. package/package.json +20 -7
  7. package/src/dom/DomAttribute.js +374 -0
  8. package/src/dom/DomBuilder.js +152 -0
  9. package/src/dom/DomEvent.js +253 -0
  10. package/src/dom/DomFinder.js +669 -0
  11. package/src/dom/DomForm.js +57 -0
  12. package/src/dom/DomGlobal.js +193 -0
  13. package/src/dom/DomInview.js +332 -0
  14. package/src/dom/DomMeta.js +66 -0
  15. package/src/dom/DomObserver.js +57 -0
  16. package/src/dom/DomRectangle.js +657 -0
  17. package/src/format/FormatFile.js +54 -0
  18. package/src/format/FormatOption.js +108 -0
  19. package/src/format/FormatParam.js +107 -0
  20. package/src/format/FormatParser.js +156 -0
  21. package/src/format/FormatUrl.js +75 -0
  22. package/src/index.browser.js +10 -0
  23. package/src/index.esm.js +138 -0
  24. package/src/now/NowDefault.js +533 -0
  25. package/src/now/NowFormat.js +196 -0
  26. package/src/now/NowGrid.js +251 -0
  27. package/src/now/NowHuman.js +118 -0
  28. package/src/now/NowMatch.js +175 -0
  29. package/src/now/NowRange.js +70 -0
  30. package/src/now/NowWalker.js +544 -0
  31. package/src/tool/scope.js +103 -0
  32. package/src/utils/Array.js +986 -0
  33. package/src/utils/Cookie.js +184 -0
  34. package/src/utils/Data.js +200 -0
  35. package/src/utils/Dom.js +208 -0
  36. package/src/utils/Event.js +140 -0
  37. package/src/utils/Format.js +62 -0
  38. package/src/utils/Hash.js +164 -0
  39. package/src/utils/Locale.js +229 -0
  40. package/src/utils/Mixed.js +887 -0
  41. package/src/utils/Now.js +234 -0
  42. package/src/utils/Number.js +238 -0
  43. package/src/utils/Object.js +655 -0
  44. package/src/utils/Route.js +67 -0
  45. package/src/utils/Runner.js +327 -0
  46. package/src/utils/String.js +618 -0
  47. package/src/{library/element.js → wip/Element.js} +90 -16
  48. package/src/{library/map.js → wip/Map.js} +256 -40
  49. package/types/dom/DomAttribute.d.ts +137 -0
  50. package/types/dom/DomBuilder.d.ts +67 -0
  51. package/types/dom/DomEvent.d.ts +103 -0
  52. package/types/dom/DomFinder.d.ts +321 -0
  53. package/types/dom/DomForm.d.ts +21 -0
  54. package/types/dom/DomGlobal.d.ts +79 -0
  55. package/types/dom/DomInview.d.ts +114 -0
  56. package/types/dom/DomMeta.d.ts +29 -0
  57. package/types/dom/DomObserver.d.ts +21 -0
  58. package/types/dom/DomRectangle.d.ts +270 -0
  59. package/types/format/FormatFile.d.ts +18 -0
  60. package/types/format/FormatOption.d.ts +40 -0
  61. package/types/format/FormatParam.d.ts +39 -0
  62. package/types/format/FormatParser.d.ts +46 -0
  63. package/types/format/FormatUrl.d.ts +17 -0
  64. package/types/index.browser.d.ts +1 -0
  65. package/types/index.esm.d.ts +52 -0
  66. package/types/now/NowDefault.d.ts +183 -0
  67. package/types/now/NowFormat.d.ts +70 -0
  68. package/types/now/NowGrid.d.ts +107 -0
  69. package/types/now/NowHuman.d.ts +37 -0
  70. package/types/now/NowMatch.d.ts +108 -0
  71. package/types/now/NowRange.d.ts +21 -0
  72. package/types/now/NowWalker.d.ts +301 -0
  73. package/types/tool/scope.d.ts +24 -0
  74. package/types/utils/Array.d.ts +480 -0
  75. package/types/utils/Cookie.d.ts +60 -0
  76. package/types/utils/Data.d.ts +91 -0
  77. package/types/utils/Dom.d.ts +138 -0
  78. package/types/utils/Event.d.ts +58 -0
  79. package/types/utils/Format.d.ts +37 -0
  80. package/types/utils/Hash.d.ts +81 -0
  81. package/types/utils/Locale.d.ts +115 -0
  82. package/types/utils/Mixed.d.ts +469 -0
  83. package/types/utils/Now.d.ts +125 -0
  84. package/types/utils/Number.d.ts +127 -0
  85. package/types/utils/Object.d.ts +255 -0
  86. package/types/utils/Route.d.ts +37 -0
  87. package/types/utils/Runner.d.ts +139 -0
  88. package/types/utils/String.d.ts +330 -0
  89. package/types/wip/Element.d.ts +119 -0
  90. package/types/wip/Map.d.ts +254 -0
  91. package/dist/.ignore.js +0 -0
  92. package/dist/pico-js.js +0 -2
  93. package/dist/pico-js.js.map +0 -1
  94. package/src/element/default.js +0 -46
  95. package/src/element/example.js +0 -58
  96. package/src/index.js +0 -90
  97. package/src/library/cookie.js +0 -123
  98. package/src/library/data.js +0 -111
  99. package/src/library/event.js +0 -91
  100. package/src/library/locale.js +0 -84
  101. package/src/library/queue.js +0 -64
  102. package/src/library/route.js +0 -28
  103. package/src/utility/any.js +0 -369
  104. package/src/utility/array.js +0 -410
  105. package/src/utility/dom.js +0 -1425
  106. package/src/utility/now.js +0 -544
  107. package/src/utility/number.js +0 -128
  108. package/src/utility/object.js +0 -429
  109. package/src/utility/string.js +0 -328
  110. package/types/index.d.ts +0 -77
  111. package/types/library/cookie.d.ts +0 -10
  112. package/types/library/data.d.ts +0 -15
  113. package/types/library/element.d.ts +0 -22
  114. package/types/library/event.d.ts +0 -13
  115. package/types/library/locale.d.ts +0 -14
  116. package/types/library/map.d.ts +0 -43
  117. package/types/library/queue.d.ts +0 -18
  118. package/types/library/route.d.ts +0 -11
  119. package/types/utility/any.d.ts +0 -35
  120. package/types/utility/array.d.ts +0 -46
  121. package/types/utility/dom.d.ts +0 -101
  122. package/types/utility/now.d.ts +0 -79
  123. package/types/utility/number.d.ts +0 -17
  124. package/types/utility/object.d.ts +0 -29
  125. package/types/utility/string.d.ts +0 -26
@@ -0,0 +1,140 @@
1
+ import { Str, Event, For, Mix, Arr } from "#src/index.esm.js";
2
+ export class PicoEvent
3
+ {
4
+ static $events = [];
5
+
6
+ /**
7
+ * Bind callback to event name
8
+ *
9
+ * @example Event.bind("x", cb) // => Event
10
+ * @example Event.bind(["a","b"], cb) // => Event
11
+ *
12
+ * @param {any} event Event name(s)
13
+ * @param {function} cb Event callback
14
+ * @param {any} [options] Listener options
15
+ * @param {boolean} [paused] Start paused
16
+ * @returns {typeof PicoEvent} Event class
17
+ */
18
+ static bind(event, cb, options = {}, paused = false)
19
+ {
20
+ if ( Mix.isArr(event) ) {
21
+ return Arr.each(event, (e) => this.bind(e, ...arguments), this);
22
+ }
23
+
24
+ if ( Mix.isPrim(options) ) {
25
+ options = { id: options };
26
+ }
27
+
28
+ this.$events = Arr.append(this.$events, {
29
+ event, cb, options, paused
30
+ });
31
+
32
+ return this;
33
+ }
34
+
35
+ /**
36
+ * Unbind callback(s) from event
37
+ *
38
+ * @example Event.unbind("x") // => Event
39
+ * @example Event.unbind(["a","b"]) // => Event
40
+ *
41
+ * @param {any} event Event name(s)
42
+ * @param {any} [options] Listener options
43
+ * @returns {typeof PicoEvent} Event class
44
+ */
45
+ static unbind(event, options = {})
46
+ {
47
+ if ( Mix.isArr(event) ) {
48
+ return Arr.each(event, (e) => this.unbind(e, ...arguments), this);
49
+ }
50
+
51
+ if ( Mix.isPrim(options) ) {
52
+ options = { id: options };
53
+ }
54
+
55
+ Arr.remove(this.$events, {
56
+ event, options
57
+ });
58
+
59
+ return this;
60
+ }
61
+
62
+ /**
63
+ * Fire event with arguments
64
+ *
65
+ * @example Event.fire("x", 1) // => Event
66
+ *
67
+ * @param {string} event Event name
68
+ * @param {...any} [args] Event args
69
+ * @returns {typeof PicoEvent} Event class
70
+ */
71
+ static fire(event, ...args)
72
+ {
73
+ let events = this.$events.filter((item) => {
74
+ return item.event === event;
75
+ });
76
+
77
+ Arr.each(events, (e) => {
78
+ if ( ! e.paused ) {
79
+ e.cb.call({}, ...args);
80
+ }
81
+ });
82
+
83
+ return this;
84
+ }
85
+
86
+ /**
87
+ * Pause listeners for event
88
+ *
89
+ * @example Event.pause("x") // => Event
90
+ *
91
+ * @param {any} event Event name(s)
92
+ * @param {any} [options] Listener options
93
+ * @returns {typeof PicoEvent} Event class
94
+ */
95
+ static pause(event, options = {})
96
+ {
97
+ if ( Mix.isArr(event) ) {
98
+ return Arr.each(event, (e) => this.pause(e, ...arguments), this);
99
+ }
100
+
101
+ let value = Arr.find(this.$events, {
102
+ event, options
103
+ });
104
+
105
+ if ( value != null ) {
106
+ value.paused = true;
107
+ }
108
+
109
+ return this;
110
+ }
111
+
112
+ /**
113
+ * Unpause listeners for event
114
+ *
115
+ * @example Event.unpause("x") // => Event
116
+ *
117
+ * @param {any} event Event name(s)
118
+ * @param {any} [options] Listener options
119
+ * @returns {typeof PicoEvent} Event class
120
+ */
121
+ static unpause(event, options = {})
122
+ {
123
+ if ( Mix.isArr(event) ) {
124
+ return Arr.each(event, (e) => this.pause(e, ...arguments), this);
125
+ }
126
+
127
+ let value = Arr.find(this.$events, {
128
+ event, options
129
+ });
130
+
131
+ if ( value != null ) {
132
+ value.paused = false;
133
+ }
134
+
135
+ return this;
136
+ }
137
+
138
+ }
139
+
140
+ export default PicoEvent;
@@ -0,0 +1,62 @@
1
+ import { PicoFormatParserPlugin } from "#src/format/FormatParser.js";
2
+ import { PicoFormatParamPlugin } from "#src/format/FormatParam.js";
3
+ import { PicoFormatOptionPlugin } from "#src/format/FormatOption.js";
4
+ import { PicoFormatUrlPlugin } from "#src/format/FormatUrl.js";
5
+ import { PicoFormatFilePlugin } from "#src/format/FormatFile.js";
6
+
7
+ export const PicoFormatPlugins = [
8
+ PicoFormatParserPlugin,
9
+ PicoFormatParamPlugin,
10
+ PicoFormatOptionPlugin,
11
+ PicoFormatUrlPlugin,
12
+ PicoFormatFilePlugin,
13
+ ];
14
+
15
+ /**
16
+ * @class PicoFormat
17
+ *
18
+ * @typedef {import('#src/format/FormatParser.js').PicoFormatParserStatic} PicoFormatParserStatic
19
+ * @typedef {import('#src/format/FormatParam.js').PicoFormatParamStatic} PicoFormatParamStatic
20
+ * @typedef {import('#src/format/FormatOption.js').PicoFormatOptionStatic} PicoFormatOptionStatic
21
+ * @typedef {import('#src/format/FormatUrl.js').PicoFormatUrlStatic} PicoFormatUrlStatic
22
+ * @typedef {import('#src/format/FormatFile.js').PicoFormatFileStatic} PicoFormatFileStatic
23
+ *
24
+ * @mixes PicoFormatParserStatic
25
+ * @mixes PicoFormatParamStatic
26
+ * @mixes PicoFormatOptionStatic
27
+ * @mixes PicoFormatUrlStatic
28
+ * @mixes PicoFormatFileStatic
29
+ */
30
+ export class PicoFormat
31
+ {
32
+
33
+ /**
34
+ * Extend format with a plugin
35
+ *
36
+ * @example For.extend(fn)
37
+ *
38
+ * @param {function} plugin Plugin function
39
+ * @returns {void} No return value
40
+ */
41
+ static extend(plugin)
42
+ {
43
+ plugin.call({}, this);
44
+ }
45
+
46
+ }
47
+
48
+ /**
49
+ * @returns {typeof PicoFormat}
50
+ */
51
+ export function PicoFormatBuilder() {
52
+
53
+ let cls = PicoFormat;
54
+
55
+ for ( const plugin of PicoFormatPlugins ) {
56
+ cls = plugin.call(cls, cls);
57
+ }
58
+
59
+ return cls;
60
+ }
61
+
62
+ export default PicoFormatBuilder;
@@ -0,0 +1,164 @@
1
+ import { Str, Hash } from "#src/index.esm.js";
2
+
3
+ /**
4
+ * @var {Array<string>} RADIX_NUMBER Radix from 0 to 9
5
+ */
6
+ export const RADIX_NUMBER = [
7
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
8
+ ];
9
+
10
+ /**
11
+ * @var {Array<string>} RADIX_LETTER_LC Radix from a to z
12
+ */
13
+ export const RADIX_LETTER_LC = [
14
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
15
+ ];
16
+
17
+ /**
18
+ * @var {Array<string>} RADIX_LETTER_UC Radix from A to Z
19
+ */
20
+ export const RADIX_LETTER_UC = [
21
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
22
+ ];
23
+
24
+ /**
25
+ * @var {Array<string>} RADIX_UUID Radix from 0-9, a-f and A-F
26
+ */
27
+ export const RADIX_UUID = [
28
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F',
29
+ ];
30
+
31
+
32
+ /**
33
+ * @var {Array<string>} RADIX_UP19 Radix with 8, 9, a and b
34
+ */
35
+ export const RADIX_UP19 = [
36
+ '8', '9', 'a', 'b',
37
+ ];
38
+
39
+ /**
40
+ * @var {Array<string>} radix_symbol_pass Radix for passwords
41
+ */
42
+ export const radix_symbol_pass = [
43
+ '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '-', '=', '[', ']', '{', '}', ';', ':', ',', '.', '/', '<', '>', '?'
44
+ ];
45
+
46
+ export class PicoHash
47
+ {
48
+
49
+ /**
50
+ * @var {Array<string>} RADIX
51
+ */
52
+ static RADIX = [
53
+ ...RADIX_NUMBER, ...RADIX_LETTER_LC, ...RADIX_LETTER_UC
54
+ ];
55
+
56
+ /**
57
+ * Get random char from radix
58
+ *
59
+ * @example Hash.radix(2, ['R', 'f']) // => 'R' or 'f'
60
+ *
61
+ * @param {number} [limit=60] Maximum radix char index
62
+ * @param {Array<string>} [radix=null] A defined radix or null for default
63
+ * @returns {string} Returns random char from radix
64
+ */
65
+ static radix(limit = 60, radix = null)
66
+ {
67
+ return (radix || this.RADIX)[this.number(limit - 1)];
68
+ }
69
+
70
+ /**
71
+ * Get random number
72
+ *
73
+ * @example Hash.number(20, 18) // => 18, 19 or 20
74
+ *
75
+ * @param {number} [limit=1024] Maximum value
76
+ * @param {number} [start=0] Minimum value
77
+ * @returns {number} Returns a random number between start and limit
78
+ */
79
+ static number(limit = 1024, start = 0)
80
+ {
81
+ return Math.floor(Math.random() * (limit - start + 1)) + start;
82
+ }
83
+
84
+ /**
85
+ * Get a random hash with given options
86
+ *
87
+ * @example Hash.make(4, 32, { 0: '?' }) // => '?8Wj'
88
+ *
89
+ * @param {number} [length] Length of generated hash
90
+ * @param {number} [radix] Maximum radix char index (10 for 0-9, 36 incl. a-z, 62 incl. A-Z)
91
+ * @param {Record<number, string>} [map] Remap for generated string
92
+ * @returns {string} Returns a random hash with fixed length
93
+ */
94
+ static make(length = 6, radix = 62, map = {})
95
+ {
96
+ let hash = '';
97
+
98
+ for ( let i = 0; i < length; i ++ ) {
99
+ hash += Hash.radix(radix);
100
+ }
101
+
102
+ for ( const k of Object.keys(map) ) {
103
+ hash = Str.set(hash, k, map[k]);
104
+ }
105
+
106
+ return hash;
107
+ }
108
+
109
+ /**
110
+ * Get a valid v4 UUID
111
+ *
112
+ * @example Hash.uuid() // => 'FBbA001F-0a01-4bE8-b29C-A9c47fA090f'
113
+ *
114
+ * @param {string|number} [version] UUID version number
115
+ * @returns {string} Returns a valid UUID
116
+ */
117
+ static uuid(version = 4)
118
+ {
119
+ let hash = '';
120
+
121
+ // Use only selected chars from the radix store
122
+ for ( let i = 0; i < 31; i ++ ) {
123
+ if ( i === 15 ) {
124
+ hash += Hash.radix(RADIX_UP19.length, RADIX_UP19);
125
+ } else {
126
+ hash += Hash.radix(RADIX_UUID.length, RADIX_UUID);
127
+ }
128
+ }
129
+
130
+ // For higher performance use substring
131
+ return hash.substring(0, 8)
132
+ + '-' + hash.substring(8, 12)
133
+ + '-' + version + hash.substring(12, 15)
134
+ + '-' + hash.substring(15, 19)
135
+ + '-' + hash.substring(19, 31);
136
+ }
137
+
138
+ /**
139
+ * Generate a password with or without symbols
140
+ *
141
+ * @example Hash.password(12, ['%', '&']) // => '0unJ%VDi2RJX'
142
+ *
143
+ * @param {number} [length=24] Length of password
144
+ * @param {Array<string>} [symbols=null] Defined symbols or null for default
145
+ * @returns {string} A random password with fixed length
146
+ */
147
+ static password(length = 24, symbols = null)
148
+ {
149
+ let radix = [
150
+ ...this.RADIX, ...(symbols || radix_symbol_pass)
151
+ ];
152
+
153
+ let hash = '';
154
+
155
+ for ( let i = 0; i < length; i ++ ) {
156
+ hash += Hash.radix(radix.length, radix);
157
+ }
158
+
159
+ return hash;
160
+ }
161
+
162
+ }
163
+
164
+ export default PicoHash;
@@ -0,0 +1,229 @@
1
+ import { Mix, Obj, Locale } from "#src/index.esm.js";
2
+
3
+ export class PicoLocale
4
+ {
5
+ /**
6
+ * Translation dictionary
7
+ *
8
+ * @type {Record<any, any>}
9
+ */
10
+ static $text = {};
11
+
12
+ /**
13
+ * Cached collator instance
14
+ *
15
+ * @type {Intl.Collator|null}
16
+ */
17
+ static $sort = null;
18
+
19
+ /**
20
+ * Active locale code
21
+ *
22
+ * @type {string}
23
+ */
24
+ static $code = 'en';
25
+
26
+ /**
27
+ * Check if translation key exists
28
+ *
29
+ * @example Locale.has("known.key") // => true
30
+ * @example Locale.has("unknown.key") // => false
31
+ *
32
+ * @param {any} [key] Translation key
33
+ * @returns {boolean} True if exists
34
+ */
35
+ static has(key = undefined)
36
+ {
37
+ if ( key === undefined ) {
38
+ return true;
39
+ }
40
+
41
+ return Mix.has(PicoLocale.$text, key);
42
+ }
43
+
44
+ /**
45
+ * Get translation value or map
46
+ *
47
+ * @example Locale.get("known.key") // => "value"
48
+ * @example Locale.get() // => object
49
+ *
50
+ * @param {any} [key] Translation key
51
+ * @param {any} [fallback] Fallback value
52
+ * @returns {any} Translation value
53
+ */
54
+ static get(key = undefined, fallback = null)
55
+ {
56
+ if ( key === undefined ) {
57
+ return PicoLocale.$text;
58
+ }
59
+
60
+ return Obj.get(PicoLocale.$text, key, fallback);
61
+ }
62
+
63
+ /**
64
+ * Set translation key or map
65
+ *
66
+ * @example Locale.set({foo:"bar"})
67
+ * @example Locale.set("unknown", "nix")
68
+ *
69
+ * @param {any} [key] Key or map
70
+ * @param {any} [value] Value to set
71
+ * @returns {any} Updated map
72
+ */
73
+ static set(key = undefined, value = undefined)
74
+ {
75
+ if ( value === undefined ) {
76
+ return PicoLocale.$text = key;
77
+ }
78
+
79
+ return Obj.set(PicoLocale.$text, key, value);
80
+ }
81
+
82
+ /**
83
+ * Get or set locale code
84
+ *
85
+ * @example Locale.code() // => "en"
86
+ * @example Locale.code("de") // => "de"
87
+ *
88
+ * @param {string|null} [code] Locale code
89
+ * @returns {string} Active code
90
+ */
91
+ static code(code = null)
92
+ {
93
+ if ( ! Mix.isNull(code) ) {
94
+ return Locale.$code = code;
95
+ }
96
+
97
+ if ( ! Mix.isNull(Locale.$code) ) {
98
+ return Locale.$code;
99
+ }
100
+
101
+ Locale.$code = (navigator.language || 'en-US')
102
+ .replace(/-[A-Z]+$/, '');
103
+
104
+ return Locale.$code;
105
+ }
106
+
107
+ /**
108
+ * Get Intl.Collator for sorting
109
+ *
110
+ * @example Locale.collator().compare("a","b")
111
+ *
112
+ * @returns {Intl.Collator} Collator instance
113
+ */
114
+ static collator()
115
+ {
116
+ if ( ! Mix.isNull(Locale.$sort) ) {
117
+ return Locale.$sort;
118
+ }
119
+
120
+ Locale.$sort = new Intl.Collator(Locale.code(), {
121
+ numeric: true, sensitivity: 'base'
122
+ });
123
+
124
+ return Locale.$sort;
125
+ }
126
+
127
+ /**
128
+ * Replace :tokens in text
129
+ *
130
+ * @example Locale.replace("Hi :x", {x:"Bob"}) // => "Hi Bob"
131
+ * @example Locale.replace("Hi", null) // => "Hi"
132
+ *
133
+ * @param {string} text Input text
134
+ * @param {any} [replace] Replace map
135
+ * @returns {string} Replaced text
136
+ */
137
+ static replace(text, replace = null)
138
+ {
139
+ if ( replace == null ) {
140
+ return text;
141
+ }
142
+
143
+ Obj.each(replace, (val, key) => {
144
+ text = text.replace(new RegExp(':' + key, 'g'), val);
145
+ });
146
+
147
+ return text;
148
+ }
149
+
150
+ /**
151
+ * Translate key with replace map
152
+ *
153
+ * @example Locale.trans("known.key") // => "..."
154
+ * @example Locale.trans("Hi :x", {x:"Bob"}) // => "Hi Bob"
155
+ *
156
+ * @param {string} text Key or text
157
+ * @param {any} [replace] Replace map
158
+ * @returns {string} Translated text
159
+ */
160
+ static trans(text, replace = null)
161
+ {
162
+ text = Obj.get(PicoLocale.$text, text, text);
163
+
164
+ return Locale.replace(text, replace);
165
+ }
166
+
167
+ /**
168
+ * Translate plural choice by count
169
+ *
170
+ * @example Locale.choice("items", 2) // => "..."
171
+ * @example Locale.choice("items", 1, {x:"y"}) // => "..."
172
+ *
173
+ * @param {string} text Key or text
174
+ * @param {number} [count] Choice count
175
+ * @param {any} [replace] Replace map
176
+ * @returns {string} Chosen text
177
+ */
178
+ static choice(text, count = 0, replace = {})
179
+ {
180
+ text = Obj.get(PicoLocale.$text, text, text);
181
+
182
+ if ( typeof replace.count === 'undefined' ) {
183
+ replace.count = count;
184
+ }
185
+
186
+ text = Locale.countpick(text.split('|'), count);
187
+
188
+ return Locale.replace(text, replace);
189
+ }
190
+
191
+ /**
192
+ * Pick plural variant from list
193
+ *
194
+ * @example Locale.countpick(["a","b"], 2) // => "b"
195
+ *
196
+ * @param {Array<string>} splits Variant list
197
+ * @param {number} count Choice count
198
+ * @returns {string} Picked text
199
+ */
200
+ static countpick(splits, count)
201
+ {
202
+ let length = splits.length;
203
+
204
+ if ( length === 3 && count === 0 ) {
205
+ return splits[0];
206
+ }
207
+
208
+ if ( length === 3 && count === 1 ) {
209
+ return splits[1];
210
+ }
211
+
212
+ if ( length === 3 && count >= 2 ) {
213
+ return splits[2];
214
+ }
215
+
216
+ if ( length === 2 && count === 1 ) {
217
+ return splits[0];
218
+ }
219
+
220
+ if ( length === 2 && count !== 1 ) {
221
+ return splits[1];
222
+ }
223
+
224
+ return splits[0];
225
+ }
226
+
227
+ }
228
+
229
+ export default PicoLocale