@cratis/scene.blueprint.default 4.35.0 → 4.36.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 (133) hide show
  1. package/ComponentName.ts +12 -0
  2. package/defaultBlueprintComponents.ts +5 -1
  3. package/dist/cjs/ComponentName.js +4 -0
  4. package/dist/cjs/ComponentName.js.map +1 -1
  5. package/dist/cjs/defaultBlueprint.js +1 -0
  6. package/dist/cjs/defaultBlueprint.js.map +1 -1
  7. package/dist/cjs/defaultBlueprintComponentMetadata.js +1 -0
  8. package/dist/cjs/defaultBlueprintComponentMetadata.js.map +1 -1
  9. package/dist/cjs/defaultBlueprintComponents.js +9 -1
  10. package/dist/cjs/defaultBlueprintComponents.js.map +1 -1
  11. package/dist/cjs/foundation/ActivityFeed.js +122 -0
  12. package/dist/cjs/foundation/ActivityFeed.js.map +1 -0
  13. package/dist/cjs/foundation/AvatarStack.js +73 -0
  14. package/dist/cjs/foundation/AvatarStack.js.map +1 -0
  15. package/dist/cjs/foundation/ChecklistSection.js +174 -0
  16. package/dist/cjs/foundation/ChecklistSection.js.map +1 -0
  17. package/dist/cjs/foundation/FileUploader.js +218 -0
  18. package/dist/cjs/foundation/FileUploader.js.map +1 -0
  19. package/dist/cjs/foundation/FileUploaderHandler.js +17 -0
  20. package/dist/cjs/foundation/FileUploaderHandler.js.map +1 -0
  21. package/dist/cjs/foundation/activityModel.js +63 -0
  22. package/dist/cjs/foundation/activityModel.js.map +1 -0
  23. package/dist/cjs/foundation/avatarModel.js +42 -0
  24. package/dist/cjs/foundation/avatarModel.js.map +1 -0
  25. package/dist/cjs/foundation/checklistModel.js +59 -0
  26. package/dist/cjs/foundation/checklistModel.js.map +1 -0
  27. package/dist/cjs/foundation/formatting.js +11 -0
  28. package/dist/cjs/foundation/formatting.js.map +1 -1
  29. package/dist/cjs/foundation/foundationComponentMetadata.js +26 -0
  30. package/dist/cjs/foundation/foundationComponentMetadata.js.map +1 -1
  31. package/dist/cjs/foundation/foundationDescriptors.js +128 -0
  32. package/dist/cjs/foundation/foundationDescriptors.js.map +1 -1
  33. package/dist/cjs/foundation/foundationSamples.js +114 -0
  34. package/dist/cjs/foundation/foundationSamples.js.map +1 -1
  35. package/dist/cjs/foundation/foundationStrings.js +15 -0
  36. package/dist/cjs/foundation/foundationStrings.js.map +1 -1
  37. package/dist/cjs/foundation/uploadModel.js +71 -0
  38. package/dist/cjs/foundation/uploadModel.js.map +1 -0
  39. package/dist/cjs/index.js +33 -0
  40. package/dist/cjs/index.js.map +1 -1
  41. package/dist/esm/ComponentName.d.ts +5 -1
  42. package/dist/esm/ComponentName.d.ts.map +1 -1
  43. package/dist/esm/ComponentName.js +4 -0
  44. package/dist/esm/ComponentName.js.map +1 -1
  45. package/dist/esm/defaultBlueprint.js +1 -0
  46. package/dist/esm/defaultBlueprint.js.map +1 -1
  47. package/dist/esm/defaultBlueprintComponentMetadata.js +1 -0
  48. package/dist/esm/defaultBlueprintComponentMetadata.js.map +1 -1
  49. package/dist/esm/defaultBlueprintComponents.d.ts.map +1 -1
  50. package/dist/esm/defaultBlueprintComponents.js +9 -1
  51. package/dist/esm/defaultBlueprintComponents.js.map +1 -1
  52. package/dist/esm/foundation/ActivityFeed.d.ts +3 -0
  53. package/dist/esm/foundation/ActivityFeed.d.ts.map +1 -0
  54. package/dist/esm/foundation/ActivityFeed.js +120 -0
  55. package/dist/esm/foundation/ActivityFeed.js.map +1 -0
  56. package/dist/esm/foundation/AvatarStack.d.ts +3 -0
  57. package/dist/esm/foundation/AvatarStack.d.ts.map +1 -0
  58. package/dist/esm/foundation/AvatarStack.js +71 -0
  59. package/dist/esm/foundation/AvatarStack.js.map +1 -0
  60. package/dist/esm/foundation/ChecklistSection.d.ts +3 -0
  61. package/dist/esm/foundation/ChecklistSection.d.ts.map +1 -0
  62. package/dist/esm/foundation/ChecklistSection.js +172 -0
  63. package/dist/esm/foundation/ChecklistSection.js.map +1 -0
  64. package/dist/esm/foundation/FileUploader.d.ts +3 -0
  65. package/dist/esm/foundation/FileUploader.d.ts.map +1 -0
  66. package/dist/esm/foundation/FileUploader.js +216 -0
  67. package/dist/esm/foundation/FileUploader.js.map +1 -0
  68. package/dist/esm/foundation/FileUploaderHandler.d.ts +8 -0
  69. package/dist/esm/foundation/FileUploaderHandler.d.ts.map +1 -0
  70. package/dist/esm/foundation/FileUploaderHandler.js +14 -0
  71. package/dist/esm/foundation/FileUploaderHandler.js.map +1 -0
  72. package/dist/esm/foundation/Foundation.stories.d.ts +8 -0
  73. package/dist/esm/foundation/Foundation.stories.d.ts.map +1 -1
  74. package/dist/esm/foundation/Foundation.stories.js +8 -0
  75. package/dist/esm/foundation/Foundation.stories.js.map +1 -1
  76. package/dist/esm/foundation/activityModel.d.ts +22 -0
  77. package/dist/esm/foundation/activityModel.d.ts.map +1 -0
  78. package/dist/esm/foundation/activityModel.js +58 -0
  79. package/dist/esm/foundation/activityModel.js.map +1 -0
  80. package/dist/esm/foundation/avatarModel.d.ts +11 -0
  81. package/dist/esm/foundation/avatarModel.d.ts.map +1 -0
  82. package/dist/esm/foundation/avatarModel.js +38 -0
  83. package/dist/esm/foundation/avatarModel.js.map +1 -0
  84. package/dist/esm/foundation/checklistModel.d.ts +17 -0
  85. package/dist/esm/foundation/checklistModel.d.ts.map +1 -0
  86. package/dist/esm/foundation/checklistModel.js +53 -0
  87. package/dist/esm/foundation/checklistModel.js.map +1 -0
  88. package/dist/esm/foundation/formatting.d.ts +1 -0
  89. package/dist/esm/foundation/formatting.d.ts.map +1 -1
  90. package/dist/esm/foundation/formatting.js +11 -1
  91. package/dist/esm/foundation/formatting.js.map +1 -1
  92. package/dist/esm/foundation/foundationComponentMetadata.d.ts.map +1 -1
  93. package/dist/esm/foundation/foundationComponentMetadata.js +26 -0
  94. package/dist/esm/foundation/foundationComponentMetadata.js.map +1 -1
  95. package/dist/esm/foundation/foundationDescriptors.d.ts.map +1 -1
  96. package/dist/esm/foundation/foundationDescriptors.js +128 -0
  97. package/dist/esm/foundation/foundationDescriptors.js.map +1 -1
  98. package/dist/esm/foundation/foundationSamples.d.ts.map +1 -1
  99. package/dist/esm/foundation/foundationSamples.js +114 -0
  100. package/dist/esm/foundation/foundationSamples.js.map +1 -1
  101. package/dist/esm/foundation/foundationStrings.d.ts +15 -0
  102. package/dist/esm/foundation/foundationStrings.d.ts.map +1 -1
  103. package/dist/esm/foundation/foundationStrings.js +15 -0
  104. package/dist/esm/foundation/foundationStrings.js.map +1 -1
  105. package/dist/esm/foundation/index.d.ts +9 -0
  106. package/dist/esm/foundation/index.d.ts.map +1 -1
  107. package/dist/esm/foundation/index.js +9 -0
  108. package/dist/esm/foundation/index.js.map +1 -1
  109. package/dist/esm/foundation/uploadModel.d.ts +31 -0
  110. package/dist/esm/foundation/uploadModel.d.ts.map +1 -0
  111. package/dist/esm/foundation/uploadModel.js +65 -0
  112. package/dist/esm/foundation/uploadModel.js.map +1 -0
  113. package/dist/esm/index.js +10 -1
  114. package/dist/esm/index.js.map +1 -1
  115. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  116. package/foundation/ActivityFeed.tsx +61 -0
  117. package/foundation/AvatarStack.tsx +43 -0
  118. package/foundation/ChecklistSection.tsx +80 -0
  119. package/foundation/FileUploader.tsx +122 -0
  120. package/foundation/FileUploaderHandler.tsx +22 -0
  121. package/foundation/Foundation.stories.tsx +8 -0
  122. package/foundation/activityModel.ts +65 -0
  123. package/foundation/avatarModel.ts +36 -0
  124. package/foundation/checklistModel.ts +62 -0
  125. package/foundation/formatting.ts +9 -0
  126. package/foundation/foundationComponentMetadata.ts +4 -0
  127. package/foundation/foundationDescriptors.ts +79 -0
  128. package/foundation/foundationSamples.ts +29 -0
  129. package/foundation/foundationStrings.ts +15 -0
  130. package/foundation/index.ts +9 -0
  131. package/foundation/uploadModel.ts +66 -0
  132. package/package.json +8 -8
  133. package/shell/layout.css +234 -0
@@ -0,0 +1,65 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+ /** Where a file is in being uploaded. */ var UploadStatus = /*#__PURE__*/ function(UploadStatus) {
4
+ UploadStatus["Queued"] = "queued";
5
+ UploadStatus["Uploading"] = "uploading";
6
+ UploadStatus["Done"] = "done";
7
+ UploadStatus["Failed"] = "failed";
8
+ return UploadStatus;
9
+ }({});
10
+ /** Why a file was refused. */ var UploadRefusal = /*#__PURE__*/ function(UploadRefusal) {
11
+ UploadRefusal["WrongType"] = "wrongType";
12
+ UploadRefusal["TooLarge"] = "tooLarge";
13
+ UploadRefusal["Single"] = "single";
14
+ return UploadRefusal;
15
+ }({});
16
+ /** Whether a file matches an `accept` list; an empty list accepts everything, and matching ignores case. */ function matchesAccept(file, accept) {
17
+ const patterns = accept.split(',').map((pattern)=>pattern.trim().toLowerCase()).filter((pattern)=>pattern.length > 0);
18
+ if (patterns.length === 0) return true;
19
+ const name = file.name.toLowerCase();
20
+ const type = file.type.toLowerCase();
21
+ return patterns.some((pattern)=>pattern.startsWith('.') ? name.endsWith(pattern) : pattern.endsWith('/*') ? type.startsWith(pattern.slice(0, -1)) : type === pattern);
22
+ }
23
+ /** Sorts a selection into the files to take and the reasons for refusing the others. Only the first is taken when one file is allowed. */ function checkSelection(files, rules, alreadySelected = 0) {
24
+ const accepted = [];
25
+ const refused = [];
26
+ for (const file of files){
27
+ if (!matchesAccept(file, rules.accept)) refused.push({
28
+ file,
29
+ reason: "wrongType"
30
+ });
31
+ else if (rules.maximumBytes > 0 && file.size > rules.maximumBytes) refused.push({
32
+ file,
33
+ reason: "tooLarge"
34
+ });
35
+ else if (!rules.multiple && alreadySelected + accepted.length >= 1) refused.push({
36
+ file,
37
+ reason: "single"
38
+ });
39
+ else accepted.push(file);
40
+ }
41
+ return {
42
+ accepted,
43
+ refused
44
+ };
45
+ }
46
+ /** A file size in the largest unit that keeps it under 1024, for the locale. */ function formatBytes(bytes, locale) {
47
+ const units = [
48
+ 'B',
49
+ 'KB',
50
+ 'MB',
51
+ 'GB'
52
+ ];
53
+ let value = bytes;
54
+ let unit = 0;
55
+ while(value >= 1024 && unit < units.length - 1){
56
+ value /= 1024;
57
+ unit++;
58
+ }
59
+ return `${new Intl.NumberFormat(locale, {
60
+ maximumFractionDigits: unit === 0 ? 0 : 1
61
+ }).format(value)} ${units[unit]}`;
62
+ }
63
+
64
+ export { UploadRefusal, UploadStatus, checkSelection, formatBytes, matchesAccept };
65
+ //# sourceMappingURL=uploadModel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uploadModel.js","sources":["../../../foundation/uploadModel.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\n/** Where a file is in being uploaded. */\nexport enum UploadStatus {\n Queued = 'queued',\n Uploading = 'uploading',\n Done = 'done',\n Failed = 'failed',\n}\n\n/** The rules a selection is checked against before anything is sent. */\nexport interface UploadRules {\n /** A comma-separated `accept` list: extensions (`.pdf`), MIME types (`image/png`) and wildcards (`image/*`). */\n accept: string;\n maximumBytes: number;\n multiple: boolean;\n}\n\n/** What the checker needs of a file. */\nexport interface SelectedFile {\n name: string;\n size: number;\n type: string;\n}\n\n/** Why a file was refused. */\nexport enum UploadRefusal {\n WrongType = 'wrongType',\n TooLarge = 'tooLarge',\n Single = 'single',\n}\n\n/** Whether a file matches an `accept` list; an empty list accepts everything, and matching ignores case. */\nexport function matchesAccept(file: SelectedFile, accept: string): boolean {\n const patterns = accept.split(',').map(pattern => pattern.trim().toLowerCase()).filter(pattern => pattern.length > 0);\n if (patterns.length === 0) return true;\n\n const name = file.name.toLowerCase();\n const type = file.type.toLowerCase();\n return patterns.some(pattern => pattern.startsWith('.') ? name.endsWith(pattern) : pattern.endsWith('/*') ? type.startsWith(pattern.slice(0, -1)) : type === pattern);\n}\n\n/** Sorts a selection into the files to take and the reasons for refusing the others. Only the first is taken when one file is allowed. */\nexport function checkSelection<T extends SelectedFile>(files: T[], rules: UploadRules, alreadySelected = 0): { accepted: T[]; refused: { file: T; reason: UploadRefusal }[] } {\n const accepted: T[] = [];\n const refused: { file: T; reason: UploadRefusal }[] = [];\n\n for (const file of files) {\n if (!matchesAccept(file, rules.accept)) refused.push({ file, reason: UploadRefusal.WrongType });\n else if (rules.maximumBytes > 0 && file.size > rules.maximumBytes) refused.push({ file, reason: UploadRefusal.TooLarge });\n else if (!rules.multiple && alreadySelected + accepted.length >= 1) refused.push({ file, reason: UploadRefusal.Single });\n else accepted.push(file);\n }\n\n return { accepted, refused };\n}\n\n/** A file size in the largest unit that keeps it under 1024, for the locale. */\nexport function formatBytes(bytes: number, locale: string): string {\n const units = ['B', 'KB', 'MB', 'GB'];\n let value = bytes;\n let unit = 0;\n while (value >= 1024 && unit < units.length - 1) { value /= 1024; unit++; }\n return `${new Intl.NumberFormat(locale, { maximumFractionDigits: unit === 0 ? 0 : 1 }).format(value)} ${units[unit]}`;\n}\n"],"names":["UploadStatus","UploadRefusal","matchesAccept","file","accept","patterns","split","map","pattern","trim","toLowerCase","filter","length","name","type","some","startsWith","endsWith","slice","checkSelection","files","rules","alreadySelected","accepted","refused","push","reason","maximumBytes","size","multiple","formatBytes","bytes","locale","units","value","unit","Intl","NumberFormat","maximumFractionDigits","format"],"mappings":"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"}
package/dist/esm/index.js CHANGED
@@ -55,7 +55,7 @@ export { LayoutModeSwitcher } from './shell/LayoutModeSwitcher.js';
55
55
  export { formatText, foundationStrings, readFoundationStrings } from './foundation/foundationStrings.js';
56
56
  export { ComponentState, componentStates, readComponentState } from './foundation/ComponentState.js';
57
57
  export { PermissionRule, readPermissionRule } from './foundation/PermissionRule.js';
58
- export { NumberFormat, formatDate, formatNumber, isRightToLeft, readLocale, readNumberFormat } from './foundation/formatting.js';
58
+ export { NumberFormat, formatDate, formatDay, formatNumber, isRightToLeft, readLocale, readNumberFormat } from './foundation/formatting.js';
59
59
  export { FoundationIcon, isFoundationIcon } from './foundation/FoundationIcon.js';
60
60
  export { ActionButton } from './foundation/ActionButton.js';
61
61
  export { EmptyStateView, FoundationFrame } from './foundation/StateFrame.js';
@@ -72,6 +72,15 @@ export { moveColumn, readColumns, toggleColumn, visibleColumnIds } from './found
72
72
  export { ColumnChooser } from './foundation/ColumnChooser.js';
73
73
  export { readViews } from './foundation/viewModel.js';
74
74
  export { SavedViewsMenu, savedViewActionOutput } from './foundation/SavedViewsMenu.js';
75
+ export { completed, doneTaskIds, isOverdue, readChecklist, toggleTask } from './foundation/checklistModel.js';
76
+ export { ChecklistSection } from './foundation/ChecklistSection.js';
77
+ export { ActivityKind, dayOf, groupByDay, readActivity } from './foundation/activityModel.js';
78
+ export { ActivityFeed } from './foundation/ActivityFeed.js';
79
+ export { initialsOf, readPeople, visiblePeople } from './foundation/avatarModel.js';
80
+ export { AvatarStack } from './foundation/AvatarStack.js';
81
+ export { UploadRefusal, UploadStatus, checkSelection, formatBytes, matchesAccept } from './foundation/uploadModel.js';
82
+ export { FileUploaderHandlerProvider, useFileUploaderHandler } from './foundation/FileUploaderHandler.js';
83
+ export { FileUploader } from './foundation/FileUploader.js';
75
84
  export { bindable, foundationDescriptors, list, standardStateProperties } from './foundation/foundationDescriptors.js';
76
85
  export { foundationComponentMetadata } from './foundation/foundationComponentMetadata.js';
77
86
  export { foundationElement, foundationSamples } from './foundation/foundationSamples.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}