@rokkit/core 1.0.0-next.36 → 1.0.0-next.38

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rokkit/core",
3
- "version": "1.0.0-next.36",
3
+ "version": "1.0.0-next.38",
4
4
  "description": "Core components, actions and stores for svelte apps.",
5
5
  "author": "Jerry Thomas <me@jerrythomas.name>",
6
6
  "license": "MIT",
@@ -13,19 +13,17 @@
13
13
  "access": "public"
14
14
  },
15
15
  "devDependencies": {
16
- "@sveltejs/vite-plugin-svelte": "^2.4.2",
16
+ "@sveltejs/vite-plugin-svelte": "^2.4.3",
17
17
  "@testing-library/svelte": "^4.0.3",
18
- "@vitest/coverage-c8": "^0.33.0",
19
- "@vitest/coverage-istanbul": "^0.33.0",
20
18
  "@vitest/coverage-v8": "^0.33.0",
21
19
  "@vitest/ui": "~0.33.0",
22
20
  "jsdom": "^22.1.0",
23
- "svelte": "^4.0.5",
21
+ "svelte": "^4.1.1",
24
22
  "typescript": "^5.1.6",
25
23
  "validators": "latest",
26
- "vite": "^4.4.4",
24
+ "vite": "^4.4.7",
27
25
  "vitest": "~0.33.0",
28
- "shared-config": "1.0.0-next.36"
26
+ "shared-config": "1.0.0-next.38"
29
27
  },
30
28
  "files": [
31
29
  "src/**/*.js",
package/src/constants.js CHANGED
@@ -4,6 +4,7 @@
4
4
  export const defaultFields = {
5
5
  id: 'id',
6
6
  url: 'url',
7
+ value: 'value',
7
8
  text: 'text',
8
9
  children: 'children',
9
10
  icon: 'icon',
@@ -51,10 +52,10 @@ export const defaultIcons = [
51
52
  'state-success',
52
53
  'state-info',
53
54
  'state-unknown',
54
- 'validity-failed',
55
- 'validity-warning',
56
- 'validity-passed',
57
- 'validity-unknown'
55
+ 'badge-fail',
56
+ 'badge-warn',
57
+ 'badge-pass',
58
+ 'badge-unknown'
58
59
  ]
59
60
 
60
61
  export const defaultOptions = {
package/src/hacks.js ADDED
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Function to change the viewport height on mobile browsers to account for the address bar
3
+ *
4
+ * @param {boolean} [browser=false] indicates whether the device is a browser
5
+ * @param {boolean} [small=false] indicates whether the device is a small mobile device
6
+ */
7
+ export function adjustViewport(browser = false, small = false) {
8
+ if (browser) {
9
+ const viewportHeight =
10
+ window.innerHeight != window.outerHeight && small
11
+ ? window.innerHeight + 'px'
12
+ : '100vh'
13
+ document.body.style.visibility = 'hidden'
14
+ document.body.style.setProperty('--viewport-height', viewportHeight)
15
+ document.body.style.visibility = 'visible'
16
+ }
17
+ }
package/src/index.js CHANGED
@@ -6,3 +6,6 @@ export * from './connector'
6
6
  export * from './ticks'
7
7
  export * from './calendar'
8
8
  export * from './utils'
9
+ export * from './parser'
10
+ export * from './string'
11
+ export * from './hacks'
package/src/mapping.js CHANGED
@@ -29,8 +29,58 @@ export function getIcon(value, fields = defaultFields) {
29
29
  : value[fields.icon]
30
30
  }
31
31
 
32
- export function getId(node, fields = defaultFields) {
32
+ export function getValue(node, fields = defaultFields) {
33
33
  return typeof node === 'object' && node !== null
34
- ? node[fields.id] ?? node[fields.text]
34
+ ? node[fields.value] ?? node[fields.text]
35
35
  : node
36
36
  }
37
+
38
+ export function getText(node, fields = defaultFields) {
39
+ return typeof node === 'object' && node !== null ? node[fields.text] : node
40
+ }
41
+
42
+ /**
43
+ * Check if the current item is a parent
44
+ *
45
+ * @param {*} item
46
+ * @param {import('./types').FieldMapping} fields
47
+ * @returns {boolean}
48
+ */
49
+ export function hasChildren(item, fields) {
50
+ return (
51
+ item != null &&
52
+ typeof item === 'object' &&
53
+ fields.children in item &&
54
+ Array.isArray(item[fields.children])
55
+ )
56
+ }
57
+
58
+ /**
59
+ * Check if the current item is a parent and is expanded
60
+ *
61
+ * @param {*} item
62
+ * @param {import('./types').FieldMapping} fields
63
+ * @returns {boolean}
64
+ */
65
+ export function isExpanded(item, fields) {
66
+ if (item == null) return false
67
+ if (!hasChildren(item, fields)) return false
68
+ if (fields.isOpen in item) {
69
+ return item[fields.isOpen]
70
+ }
71
+ return false
72
+ }
73
+
74
+ /**
75
+ * Verify if at least one item has children
76
+ *
77
+ * @param {Array<*>} items
78
+ * @param {import('./types').FieldMapping} fields
79
+ * @returns {boolean}
80
+ */
81
+ export function isNested(items, fields) {
82
+ for (let i = 0; i < items.length; i++) {
83
+ if (hasChildren(items[i], fields)) return true
84
+ }
85
+ return false
86
+ }
package/src/parser.js ADDED
@@ -0,0 +1,53 @@
1
+ export function getRegex() {
2
+ let column = '[\\w]+'
3
+ let operator = ':|>|<|>=|<=|=<|=>|=|!=|~|~\\*|!~|!~\\*'
4
+ let value = '("[^"]+"|[^\\s=:<>!~*]+)'
5
+
6
+ let pattern = `(?<group>((?<column>${column})\\s?(?<operator>${operator})\\s?)(?<value>${value}))`
7
+
8
+ return new RegExp(pattern, 'gm')
9
+ }
10
+
11
+ export function parseFilters(string) {
12
+ const results = []
13
+ const regex = getRegex()
14
+
15
+ // Split the string into an array of tokens
16
+ const tokens = string.matchAll(regex)
17
+ let search = string
18
+ // Iterate over the tokens
19
+ for (const token of tokens) {
20
+ // Extract the named groups from the token
21
+ let { group, column, operator, value } = token.groups
22
+ search = search.replace(group, '').trim()
23
+
24
+ operator = operator
25
+ .replace(':', '~*')
26
+ .replace('=>', '>=')
27
+ .replace('=<', '<=')
28
+
29
+ if (value) {
30
+ value = !isNaN(parseInt(value)) ? parseInt(value) : removeQuotes(value)
31
+
32
+ if (operator.includes('~')) {
33
+ value = operator.includes('*')
34
+ ? new RegExp(value, 'i')
35
+ : new RegExp(value)
36
+ }
37
+ }
38
+ if (column && value) results.push({ column, operator, value })
39
+ }
40
+ if (search.length > 0) {
41
+ results.push({
42
+ operator: '~*',
43
+ value: new RegExp(removeQuotes(search), 'i')
44
+ })
45
+ }
46
+
47
+ return results
48
+ }
49
+
50
+ function removeQuotes(str) {
51
+ const quoteMatch = str.match(/^"([^"]+)"$/)
52
+ return quoteMatch ? quoteMatch[1] : str
53
+ }
package/src/string.js ADDED
@@ -0,0 +1,96 @@
1
+ import { filter } from 'ramda'
2
+ /**
3
+ * Capitalizes the first letter of input string
4
+ *
5
+ * @param {String} str
6
+ * @returns {String}
7
+ */
8
+ export function toInitCapCase(text) {
9
+ return text.charAt(0).toUpperCase() + text.slice(1).toLowerCase()
10
+ }
11
+
12
+ /**
13
+ * Convert a hyphen separated string to PascalCase
14
+ *
15
+ * @param {String} text
16
+ * @returns
17
+ */
18
+ export function toPascalCase(text) {
19
+ return text
20
+ .split('-')
21
+ .map((part) => toInitCapCase(part))
22
+ .join('')
23
+ }
24
+
25
+ /**
26
+ * Convert a PascalCase string to snake case with separator as hyphen
27
+ *
28
+ * @param {Strin} text
29
+ * @returns
30
+ */
31
+ export function toHyphenCase(text) {
32
+ return text
33
+ .replace(/\s+/, '-')
34
+ .replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`)
35
+ .replace(/^-/, '')
36
+ }
37
+
38
+ /**
39
+ * Sort by splitting hyphen separated strings while keeping strings with same number of parts together
40
+ *
41
+ * @param {String} a hyphen separates string
42
+ * @param {String} b hyphen separates string
43
+ * @returns
44
+ */
45
+ export function sortByParts(a, b) {
46
+ const partsOfA = a.split('-')
47
+ const partsOfB = b.split('-')
48
+
49
+ let result = compareStrings(partsOfA[0], partsOfB[0])
50
+ if (result == 0) result = partsOfA.length - partsOfB.length
51
+ if (result == 0) result = compareStrings(a, b)
52
+ return result
53
+ }
54
+
55
+ /**
56
+ * Simple comparison for two strings
57
+ *
58
+ * @param {String} a
59
+ * @param {String} b
60
+ * @returns
61
+ */
62
+ export function compareStrings(a, b) {
63
+ return a > b ? 1 : a < b ? -1 : 0
64
+ }
65
+
66
+ /**
67
+ * Generates a unique id from current timestamp
68
+ *
69
+ * @returns {String} timestamp based unique id
70
+ */
71
+ export function uniqueId(prefix = '', separator = '-') {
72
+ let pair = prefix && prefix.length > 0 ? [prefix] : []
73
+ pair.push(Date.now().toString(36))
74
+ return pair.join(separator)
75
+ }
76
+
77
+ /**
78
+ * Removes undefined and null values from the input object.
79
+ *
80
+ * @param {Object} obj
81
+ * @returns {Object}
82
+ */
83
+ export function compact(obj) {
84
+ return filter((x) => x !== undefined && x !== null, obj)
85
+ }
86
+
87
+ /**
88
+ * Converts an input number into it's hexadecimal representation, with optional left padded zeroes based on the `size`
89
+ *
90
+ * @param {number} value
91
+ * @param {number} size
92
+ * @returns
93
+ */
94
+ export function toHexString(value, size = 2) {
95
+ return value.toString(16).padStart(size, '0')
96
+ }
package/src/ticks.js CHANGED
@@ -2,15 +2,19 @@ export function generateTicks(
2
2
  lowerBound,
3
3
  upperBound,
4
4
  minorTickStep,
5
- majorTickStep = 1
5
+ majorTickStep = 1,
6
+ formatter = new Intl.NumberFormat('en-US', { CompactDisplay: 'short' })
6
7
  ) {
7
8
  minorTickStep = minorTickStep ? minorTickStep : upperBound - lowerBound
8
9
  const length = 1 + Math.ceil((upperBound - lowerBound) / minorTickStep)
9
10
  const ticks = Array.from({ length }, (_, i) => ({
10
11
  value: i == length - 1 ? upperBound : lowerBound + minorTickStep * i,
11
12
  major: i == 0 || i == length - 1 || i % majorTickStep == 0
13
+ })).map(({ value, major }) => ({
14
+ value,
15
+ label: major ? formatter.format(value) : '',
16
+ major
12
17
  }))
13
- //.map(({ value, show }) => ({ value, label: show ? value : '', major }))
14
18
 
15
19
  return ticks
16
20
  }
package/src/utils.js CHANGED
@@ -1,3 +1,91 @@
1
+ const modifiers = {
2
+ hsl: (value) => `hsl(${value})`,
3
+ rgb: (value) => `rgb(${value})`,
4
+ none: (value) => value
5
+ }
6
+
1
7
  export function id() {
2
8
  return Math.random().toString(36).substr(2, 9)
3
9
  }
10
+
11
+ /**
12
+ * Generate shades for a color using css varuable
13
+ *
14
+ * @param {string} name
15
+ * @returns
16
+ */
17
+ export function shadesOf(name, modifier = 'none') {
18
+ const shades = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900]
19
+ const fn = modifier in modifiers ? modifiers[modifier] : modifiers.none
20
+
21
+ return shades.reduce(
22
+ (result, shade) => ({
23
+ ...result,
24
+ [shade]: fn(`var(--${name}-${shade})`)
25
+ }),
26
+ {
27
+ DEFAULT: fn(`var(--${name}-500)`),
28
+ inset: fn(`var(--${name}-50)`),
29
+ sunken: fn(`var(--${name}-50)`),
30
+ recessed: fn(`var(--${name}-50)`),
31
+ base: fn(`var(--${name}-100)`),
32
+ subtle: fn(`var(--${name}-200)`),
33
+ muted: fn(`var(--${name}-300)`),
34
+ raised: fn(`var(--${name}-400)`),
35
+ elevated: fn(`var(--${name}-500)`),
36
+ floating: fn(`var(--${name}-600)`),
37
+ contrast: fn(`var(--${name}-700)`)
38
+ }
39
+ )
40
+ }
41
+
42
+ export function stateColors(name, modifier = 'none') {
43
+ const fn = modifier in modifiers ? modifiers[modifier] : modifiers.none
44
+ return {
45
+ DEFAULT: fn(`var(--${name}-500)`),
46
+ light: fn(`var(--${name}-100)`),
47
+ dark: fn(`var(--${name}-800)`)
48
+ }
49
+ }
50
+
51
+ export function themeColors(modifier = 'none') {
52
+ const fn = modifier in modifiers ? modifiers[modifier] : modifiers.none
53
+
54
+ let states = ['info', 'error', 'warn', 'pass']
55
+ let variants = ['skin', 'primary', 'secondary', 'accent']
56
+ let colors = states.reduce(
57
+ (acc, state) => ({ ...acc, [state]: stateColors(state, modifier) }),
58
+ {}
59
+ )
60
+ colors = variants.reduce(
61
+ (acc, variant) => ({ ...acc, [variant]: shadesOf(variant, modifier) }),
62
+ colors
63
+ )
64
+ colors.skin = {
65
+ ...colors.skin,
66
+ contrast: fn(`var(--skin-800)`),
67
+ zebra: fn(`var(--skin-zebra)`)
68
+ }
69
+
70
+ return colors
71
+ }
72
+
73
+ export function iconShortcuts(icons, collection, variants) {
74
+ const suffix = variants ? `-${variants}` : ''
75
+ const shortcuts = !collection
76
+ ? {}
77
+ : icons.reduce(
78
+ (acc, name) => ({
79
+ ...acc,
80
+ [name]: [collection, name].join(':') + suffix
81
+ }),
82
+ {}
83
+ )
84
+
85
+ return shortcuts
86
+ }
87
+
88
+ export function scaledPath(size, x) {
89
+ if (Array.isArray(x)) return x.map((x) => scaledPath(size, x)).join(' ')
90
+ return typeof x === 'number' ? x * size : x
91
+ }