@aws-amplify/ui 6.6.2 → 6.6.4

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.
@@ -18,8 +18,9 @@ export { createTheme } from './theme/createTheme/createTheme.mjs';
18
18
  export { defineComponentTheme } from './theme/createTheme/defineComponentTheme.mjs';
19
19
  export { createComponentCSS } from './theme/createTheme/createComponentCSS.mjs';
20
20
  export { createGlobalCSS } from './theme/createTheme/createGlobalCSS.mjs';
21
- export { cssNameTransform, isDesignToken, setupTokens } from './theme/createTheme/utils.mjs';
21
+ export { cssNameTransform, deepExtend, isDesignToken, setupTokens } from './theme/createTheme/utils.mjs';
22
22
  export { createComponentClasses } from './theme/createTheme/createComponentClasses.mjs';
23
+ export { resolveObject } from './theme/createTheme/resolveObject.mjs';
23
24
  export { defaultTheme } from './theme/defaultTheme.mjs';
24
25
  export { defaultDarkModeOverride, reactNativeDarkTokens } from './theme/defaultDarkModeOverride.mjs';
25
26
  export { reactNativeTokens } from './theme/tokens/index.mjs';
@@ -28,6 +29,7 @@ export { isUnverifiedContactMethodType } from './types/authenticator/utils.mjs';
28
29
  export { LoginMechanismArray, authFieldsWithDefaults, isAuthFieldsWithDefaults, signUpFieldsWithDefault, signUpFieldsWithoutDefault } from './types/authenticator/attributes.mjs';
29
30
  export { ComponentClassName } from './types/primitives/componentClassName.mjs';
30
31
  export { setUserAgent } from './utils/setUserAgent/setUserAgent.mjs';
31
- export { areEmptyArrays, areEmptyObjects, capitalize, classNameModifier, classNameModifierByFlag, groupLog, has, isEmpty, isEmptyObject, isFunction, isMap, isNil, isObject, isSet, isString, isUndefined, noop, sanitizeNamespaceImport, splitObject, templateJoin } from './utils/utils.mjs';
32
+ export { areEmptyArrays, areEmptyObjects, capitalize, classNameModifier, classNameModifierByFlag, cloneDeep, groupLog, has, isEmpty, isEmptyObject, isFunction, isMap, isNil, isObject, isSet, isString, isUndefined, noop, sanitizeNamespaceImport, splitObject, templateJoin } from './utils/utils.mjs';
32
33
  export { classNames } from './utils/classNames.mjs';
33
34
  export { humanFileSize } from './utils/humanFileSize.mjs';
35
+ export { getName, getPathFromName, resolveReference, usesReference } from './utils/references.mjs';
@@ -0,0 +1,8 @@
1
+ const OPTIONS = {
2
+ openingCharacter: '{',
3
+ closingCharacter: '}',
4
+ separator: '.',
5
+ };
6
+ const REFERENCE_REGEX = /\{([^}]+)\}/g;
7
+
8
+ export { OPTIONS, REFERENCE_REGEX };
@@ -0,0 +1,133 @@
1
+ import '@aws-amplify/core/internals/utils';
2
+ import '../../utils/setUserAgent/constants.mjs';
3
+ import { cloneDeep, has } from '../../utils/utils.mjs';
4
+ import { getName, getPathFromName, resolveReference, usesReference } from '../../utils/references.mjs';
5
+ import { REFERENCE_REGEX } from './constants.mjs';
6
+
7
+ const DEFAULTS = {
8
+ ignoreKeys: ['original'],
9
+ };
10
+ function resolveObject(object) {
11
+ const foundCirc = {};
12
+ const clone = cloneDeep(object); // This object will be edited
13
+ const currentContext = []; // To maintain the context to be able to test for circular definitions
14
+ if (typeof object === 'object') {
15
+ return traverseObject({
16
+ slice: clone,
17
+ fullObj: clone,
18
+ currentContext,
19
+ foundCirc,
20
+ });
21
+ }
22
+ else {
23
+ throw new Error('Please pass an object in');
24
+ }
25
+ }
26
+ /**
27
+ * Recursively traverses an object (slice) to resolve and uses
28
+ * compileValue to replace any string references found within it
29
+ */
30
+ function traverseObject({ slice, fullObj, currentContext, foundCirc, }) {
31
+ for (let key in slice) {
32
+ if (!has(slice, key)) {
33
+ continue;
34
+ }
35
+ const prop = slice[key];
36
+ // We want to check for ignoredKeys, this is to
37
+ // skip over attributes that should not be
38
+ // mutated, like a copy of the original property.
39
+ if (DEFAULTS.ignoreKeys && DEFAULTS.ignoreKeys.indexOf(key) !== -1) {
40
+ continue;
41
+ }
42
+ currentContext.push(key);
43
+ if (typeof prop === 'object') {
44
+ traverseObject({ currentContext, slice: prop, fullObj, foundCirc });
45
+ }
46
+ else {
47
+ if (typeof prop === 'string' && prop.indexOf('{') > -1) {
48
+ slice[key] = compileValue({
49
+ value: prop,
50
+ stack: [getName(currentContext)],
51
+ foundCirc,
52
+ fullObj,
53
+ });
54
+ }
55
+ }
56
+ currentContext.pop();
57
+ }
58
+ return fullObj;
59
+ }
60
+ /**
61
+ * Resolves references in a value, performing recursive lookups when references are nested.
62
+ * value: The string that may contain references (e.g., {color.border.light}) that need to be replaced
63
+ * stack: keeps track of the current chain of references to detect circular references
64
+ * foundCirc: stores any detected circular references
65
+ * fullObj: The full object where references are looked up, essentially the source of all values
66
+ */
67
+ function compileValue({ value, stack, foundCirc, fullObj }) {
68
+ let toRet = value, ref;
69
+ const regex = new RegExp(REFERENCE_REGEX);
70
+ // Replace the reference inline, but don't replace the whole string because
71
+ // references can be part of the value such as "1px solid {color.border.light}"
72
+ value.replace(regex, function (match, variable) {
73
+ variable = variable.trim();
74
+ // Find what the value is referencing
75
+ const pathName = getPathFromName(variable);
76
+ const refHasValue = pathName[pathName.length - 1] === 'value';
77
+ stack.push(variable);
78
+ ref = resolveReference(pathName, fullObj);
79
+ // If the reference doesn't end in 'value'
80
+ // and
81
+ // the reference points to someplace that has a `value` attribute
82
+ // we should take the '.value' of the reference
83
+ // per the W3C draft spec where references do not have .value
84
+ // https://design-tokens.github.io/community-group/format/#aliases-references
85
+ if (!refHasValue && ref && has(ref, 'value')) {
86
+ ref = ref.value;
87
+ }
88
+ if (typeof ref !== 'undefined') {
89
+ if (typeof ref === 'string' || typeof ref === 'number') {
90
+ toRet = value.replace(match, ref);
91
+ // Recursive, therefore we can compute multi-layer variables like a = b, b = c, eventually a = c
92
+ if (usesReference(toRet)) {
93
+ var reference = toRet.slice(1, -1);
94
+ // Compare to found circular references
95
+ if (has(foundCirc, reference)) ;
96
+ else if (stack.indexOf(reference) !== -1) {
97
+ // If the current stack already contains the current reference, we found a new circular reference
98
+ // chop down only the circular part, save it to our circular reference info, and spit out an error
99
+ // Get the position of the existing reference in the stack
100
+ var stackIndexReference = stack.indexOf(reference);
101
+ // Get the portion of the stack that starts at the circular reference and brings you through until the end
102
+ var circStack = stack.slice(stackIndexReference);
103
+ // For all the references in this list, add them to the list of references that end up in a circular reference
104
+ circStack.forEach(function (key) {
105
+ foundCirc[key] = true;
106
+ });
107
+ // Add our found circular reference to the end of the cycle
108
+ circStack.push(reference);
109
+ }
110
+ else {
111
+ toRet = compileValue({ value: toRet, stack, foundCirc, fullObj });
112
+ }
113
+ }
114
+ // if evaluated value is a number and equal to the reference, we want to keep the type
115
+ if (typeof ref === 'number' && ref.toString() === toRet) {
116
+ toRet = ref;
117
+ }
118
+ }
119
+ else {
120
+ // if evaluated value is not a string or number, we want to keep the type
121
+ toRet = ref;
122
+ }
123
+ }
124
+ else {
125
+ toRet = ref;
126
+ }
127
+ stack.pop(variable);
128
+ return toRet;
129
+ });
130
+ return toRet;
131
+ }
132
+
133
+ export { compileValue, resolveObject, traverseObject };
@@ -2,6 +2,7 @@ import kebabCase from 'lodash/kebabCase.js';
2
2
  import '@aws-amplify/core/internals/utils';
3
3
  import '../../utils/setUserAgent/constants.mjs';
4
4
  import { isObject, has, isString } from '../../utils/utils.mjs';
5
+ import { usesReference } from '../../utils/references.mjs';
5
6
 
6
7
  const CSS_VARIABLE_PREFIX = 'amplify';
7
8
  /**
@@ -203,34 +204,5 @@ function deepExtend(objects, collision, path) {
203
204
  }
204
205
  return target;
205
206
  }
206
- /**
207
- * Checks if the value uses a value reference.
208
- * @param {string} value
209
- * @returns {boolean} - True, if the value uses a value reference
210
- */
211
- function usesReference(value) {
212
- const regex = new RegExp('\\{([^}]+)\\}', 'g');
213
- if (typeof value === 'string') {
214
- return regex.test(value);
215
- }
216
- if (typeof value === 'object') {
217
- let hasReference = false;
218
- // iterate over each property in the object,
219
- // if any element passes the regex test,
220
- // the whole thing should be true
221
- for (const key in value) {
222
- if (has(value, key)) {
223
- const element = value[key];
224
- let reference = usesReference(element);
225
- if (reference) {
226
- hasReference = true;
227
- break;
228
- }
229
- }
230
- }
231
- return hasReference;
232
- }
233
- return false;
234
- }
235
207
 
236
- export { CSS_VARIABLE_PREFIX, cssNameTransform, cssValue, deepExtend, flattenProperties, isDesignToken, isShadowTokenObject, propsToString, referenceValue, setupToken, setupTokens, usesReference };
208
+ export { CSS_VARIABLE_PREFIX, cssNameTransform, cssValue, deepExtend, flattenProperties, isDesignToken, isShadowTokenObject, propsToString, referenceValue, setupToken, setupTokens };
@@ -0,0 +1,65 @@
1
+ const aiConversation = {
2
+ message: {
3
+ backgroundColor: { value: '{colors.background.secondary.value}' },
4
+ borderRadius: { value: '{radii.large.value}' },
5
+ gap: { value: '{space.small.value}' },
6
+ paddingBlock: { value: '{space.small.value}' },
7
+ paddingInline: { value: '{space.small.value}' },
8
+ user: {
9
+ backgroundColor: { value: '{colors.background.secondary.value}' },
10
+ },
11
+ assistant: {
12
+ backgroundColor: { value: '{colors.primary.10.value}' },
13
+ },
14
+ sender: {
15
+ gap: { value: '{space.small.value}' },
16
+ username: {
17
+ color: { value: '{colors.font.primary.value}' },
18
+ fontSize: { value: 'inherit' },
19
+ fontWeight: { value: '{fontWeights.bold.value}' },
20
+ },
21
+ timestamp: {
22
+ color: { value: '{colors.font.tertiary.value}' },
23
+ fontSize: { value: 'inherit' },
24
+ fontWeight: { value: 'inherit' },
25
+ },
26
+ },
27
+ body: { gap: { value: '{space.xs.value}' } },
28
+ },
29
+ form: {
30
+ gap: { value: '{space.small.value}' },
31
+ padding: { value: '{space.small.value}' },
32
+ },
33
+ attachment: {
34
+ borderColor: { value: '{colors.border.secondary.value}' },
35
+ borderWidth: { value: '{borderWidths.small.value}' },
36
+ borderRadius: { value: '{radii.small.value}' },
37
+ fontSize: { value: '{fontSizes.small.value}' },
38
+ paddingBlock: { value: '{space.xxxs.value}' },
39
+ paddingInline: { value: '{space.xs.value}' },
40
+ gap: { value: '{space.xs.value}' },
41
+ list: {
42
+ paddingBlockStart: { value: '{space.xs.value}' },
43
+ gap: { value: '{space.xxs.value}' },
44
+ },
45
+ name: {
46
+ color: { value: '{colors.font.primary.value}' },
47
+ fontSize: { value: '{fontSizes.small.value}' },
48
+ fontWeight: { value: '{fontWeights.normal.value}' },
49
+ },
50
+ size: {
51
+ color: { value: '{colors.font.tertiary.value}' },
52
+ fontSize: { value: '{fontSizes.small.value}' },
53
+ fontWeight: { value: '{fontWeights.normal.value}' },
54
+ },
55
+ remove: {
56
+ padding: { value: '{space.xxs.value}' },
57
+ },
58
+ image: {
59
+ width: { value: '{fontSizes.medium.value}' },
60
+ height: { value: '{fontSizes.medium.value}' },
61
+ },
62
+ },
63
+ };
64
+
65
+ export { aiConversation };
@@ -1,4 +1,5 @@
1
1
  import { alert } from './alert.mjs';
2
+ import { aiConversation } from './aiConversation.mjs';
2
3
  import { autocomplete } from './autocomplete.mjs';
3
4
  import { authenticator } from './authenticator.mjs';
4
5
  import { avatar } from './avatar.mjs';
@@ -56,6 +57,7 @@ import { togglebuttongroup } from './toggleButtonGroup.mjs';
56
57
 
57
58
  const components = {
58
59
  accordion,
60
+ aiConversation,
59
61
  alert,
60
62
  authenticator,
61
63
  autocomplete,
@@ -0,0 +1,70 @@
1
+ import { has } from './utils.mjs';
2
+ import { OPTIONS, REFERENCE_REGEX } from '../theme/createTheme/constants.mjs';
3
+
4
+ /**
5
+ * Checks if the value uses a value reference.
6
+ * @param {string} value
7
+ * @returns {boolean} - True, if the value uses a value reference
8
+ */
9
+ function usesReference(value) {
10
+ const regex = new RegExp(REFERENCE_REGEX);
11
+ if (typeof value === 'string') {
12
+ return regex.test(value);
13
+ }
14
+ if (typeof value === 'object') {
15
+ let hasReference = false;
16
+ // iterate over each property in the object,
17
+ // if any element passes the regex test,
18
+ // the whole thing should be true
19
+ for (const key in value) {
20
+ if (has(value, key)) {
21
+ const element = value[key];
22
+ let reference = usesReference(element);
23
+ if (reference) {
24
+ hasReference = true;
25
+ break;
26
+ }
27
+ }
28
+ }
29
+ return hasReference;
30
+ }
31
+ return false;
32
+ }
33
+ function resolveReference(path, obj) {
34
+ let ref = obj;
35
+ if (!Array.isArray(path)) {
36
+ return;
37
+ }
38
+ for (let i = 0; i < path.length; i++) {
39
+ // Check for undefined as 0 is a valid, truthy value
40
+ if (typeof ref[path[i]] !== 'undefined') {
41
+ ref = ref[path[i]];
42
+ }
43
+ else {
44
+ // set the reference as undefined if we don't find anything
45
+ ref = undefined;
46
+ break;
47
+ }
48
+ }
49
+ return ref;
50
+ }
51
+ /**
52
+ * Returns the path from a path name be splitting the name by a given separator.
53
+ */
54
+ function getPathFromName(pathName) {
55
+ if (typeof pathName !== 'string') {
56
+ throw new Error('Getting path from name failed. Name must be a string');
57
+ }
58
+ return pathName.split(OPTIONS.separator);
59
+ }
60
+ /**
61
+ * Returns the paths name be joining its parts with a given separator.
62
+ */
63
+ function getName(path) {
64
+ if (!path || !(path instanceof Array)) {
65
+ throw new Error('Getting name for path failed. Path must be an array');
66
+ }
67
+ return path.join(OPTIONS.separator);
68
+ }
69
+
70
+ export { getName, getPathFromName, resolveReference, usesReference };
@@ -234,5 +234,22 @@ function splitObject(obj, predicate) {
234
234
  });
235
235
  return [left, right];
236
236
  }
237
+ const cloneDeep = (obj) => {
238
+ if (obj === null || obj === undefined || typeof obj !== 'object') {
239
+ return obj;
240
+ }
241
+ if (obj instanceof Array) {
242
+ return obj.reduce((arr, item, i) => {
243
+ arr[i] = cloneDeep(item);
244
+ return arr;
245
+ }, []);
246
+ }
247
+ if (obj instanceof Object) {
248
+ return Object.keys(obj || {}).reduce((cpObj, key) => {
249
+ cpObj[key] = cloneDeep(obj[key]);
250
+ return cpObj;
251
+ }, {});
252
+ }
253
+ };
237
254
 
238
- export { areEmptyArrays, areEmptyObjects, capitalize, classNameModifier, classNameModifierByFlag, groupLog, has, isEmpty, isEmptyObject, isFunction, isMap, isNil, isObject, isSet, isString, isUndefined, noop, sanitizeNamespaceImport, splitObject, templateJoin };
255
+ export { areEmptyArrays, areEmptyObjects, capitalize, classNameModifier, classNameModifierByFlag, cloneDeep, groupLog, has, isEmpty, isEmptyObject, isFunction, isMap, isNil, isObject, isSet, isString, isUndefined, noop, sanitizeNamespaceImport, splitObject, templateJoin };