@opensalt/ob3-definer 1.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 (45) hide show
  1. package/.vscode/extensions.json +3 -0
  2. package/LICENSE +21 -0
  3. package/README.md +86 -0
  4. package/dist/favicon.svg +7 -0
  5. package/dist/index.html +20 -0
  6. package/dist/ob3-definer.css +1 -0
  7. package/dist/ob3-definer.js +32 -0
  8. package/formkit.config.js +27 -0
  9. package/index.html +19 -0
  10. package/jsconfig.json +8 -0
  11. package/package.json +35 -0
  12. package/public/favicon.svg +7 -0
  13. package/src/App.vue +19 -0
  14. package/src/assets/base.css +86 -0
  15. package/src/assets/main.css +24 -0
  16. package/src/assets/style.scss +33 -0
  17. package/src/components/AchievementCriteria.vue +78 -0
  18. package/src/components/AchievementDefiner.vue +212 -0
  19. package/src/components/AchievementImage.vue +116 -0
  20. package/src/components/AchievementType.vue +111 -0
  21. package/src/components/AdditionalTab.vue +32 -0
  22. package/src/components/AddressComponent.vue +118 -0
  23. package/src/components/AlignmentComponent.vue +141 -0
  24. package/src/components/AlignmentsComponent.vue +13 -0
  25. package/src/components/AlignmentsTab.vue +18 -0
  26. package/src/components/BasicTab.vue +55 -0
  27. package/src/components/CreatorProfile.vue +166 -0
  28. package/src/components/CriterionLevels.vue +97 -0
  29. package/src/components/DetailTab.vue +72 -0
  30. package/src/components/IndividualName.vue +63 -0
  31. package/src/components/MarkdownRenderer.vue +20 -0
  32. package/src/components/OtherIdentifiers.vue +116 -0
  33. package/src/components/RelatedList.vue +89 -0
  34. package/src/components/ResultDescription.vue +120 -0
  35. package/src/components/ResultType.vue +94 -0
  36. package/src/components/TagList.vue +121 -0
  37. package/src/components/ValueList.vue +144 -0
  38. package/src/inputs/innerLabelTextInput.js +62 -0
  39. package/src/inputs/innerLabelTextareaInput.js +57 -0
  40. package/src/inputs/selectInputGroup.js +76 -0
  41. package/src/main.js +50 -0
  42. package/src/stores/credential.js +292 -0
  43. package/test-index.html +17 -0
  44. package/trial-key +3 -0
  45. package/vite.config.js +39 -0
@@ -0,0 +1,121 @@
1
+ <script setup>
2
+ import {onBeforeMount, ref, watch} from "vue";
3
+ import {FormKitIcon} from '@formkit/vue'
4
+ import {vAutoAnimate} from '@formkit/auto-animate'
5
+
6
+ const values = ref([]);
7
+ const model = defineModel({ default: [] });
8
+
9
+ onBeforeMount(() => {
10
+ values.value = model.value;
11
+ });
12
+ function distinct(node) {
13
+ // 👀 use node traversal to get the parent node
14
+ const parent = node.at('$parent')
15
+ if (parent.value) {
16
+ // Ensure all the siblings are different values
17
+ for (const childName in parent.value) {
18
+ if (''+childName === ''+node.name) {
19
+ continue;
20
+ }
21
+ if (parent.value[childName] === node.value) {
22
+ return false;
23
+ }
24
+ }
25
+ }
26
+ return true
27
+ }
28
+
29
+ watch(values, (newValues) => {
30
+ model.value = newValues;
31
+ });
32
+ </script>
33
+
34
+ <template>
35
+ <div v-auto-animate>
36
+ <FormKit v-model="values" name="tag" type="list" dynamic #default="{ items, node, value }">
37
+ <h5>Tags
38
+ <button type="button" @click="values.push(null)" class="btn btn-sm btn-primary ms-3">
39
+ Add Tag
40
+ </button>
41
+ </h5>
42
+ <p class="form-text">One or more short, human-friendly, searchable, keywords that describe the type of achievement.</p>
43
+
44
+ <div class="ms-5 mb-3 p-3 border rounded" v-if="items.length > 0">
45
+ <div v-for="(item, index) in items" :key="item" class="value-item">
46
+ <FormKit
47
+ type="text"
48
+ :index="index"
49
+ :validation-rules="{ distinct }"
50
+ validation="required:trim|distinct"
51
+ placeholder="Enter tag"
52
+ :validation-messages="{
53
+ 'required': 'Value is required',
54
+ 'distinct': 'The tags must be distinct',
55
+ }"
56
+ outer-class="$reset"
57
+ />
58
+ <ul class="controls mt-2">
59
+ <li>
60
+ <button
61
+ type="button"
62
+ @click="values.splice(index, 1)"
63
+ class="button close"
64
+ >
65
+ <FormKitIcon icon="close"/>
66
+ </button>
67
+ </li>
68
+ </ul>
69
+ </div>
70
+ </div>
71
+ </FormKit>
72
+ </div>
73
+ </template>
74
+
75
+ <style scoped>
76
+ .value-item {
77
+ display: flex;
78
+ align-items: start;
79
+ margin-bottom: 0.5rem;
80
+ }
81
+
82
+ .value-item:deep(.formkit-outer) {
83
+ margin-bottom: 0;
84
+ flex-grow: 1;
85
+ }
86
+
87
+ .controls {
88
+ list-style-type: none;
89
+ margin: 0;
90
+ padding: 0;
91
+ display: flex;
92
+ align-items: center;
93
+ }
94
+
95
+ .controls .button {
96
+ border: none;
97
+ background: none;
98
+ padding: 0;
99
+ margin: 0;
100
+ cursor: pointer;
101
+ color: #999;
102
+ line-height: 1;
103
+ transition: color 0.3s ease;
104
+ appearance: none;
105
+ font-size: 1em;
106
+ color: var(--fk-color-primary);
107
+ margin-left: 0.5rem;
108
+ }
109
+
110
+ .controls:deep(svg) {
111
+ display: block;
112
+ width: 1em;
113
+ max-height: 1.25em;
114
+ height: auto;
115
+ fill: currentColor;
116
+ }
117
+
118
+ .controls .close {
119
+ color: var(--fk-color-danger);
120
+ }
121
+ </style>
@@ -0,0 +1,144 @@
1
+ <script setup>
2
+ import {ref, watch} from "vue";
3
+ import {FormKitIcon} from '@formkit/vue'
4
+ import {vAutoAnimate} from '@formkit/auto-animate'
5
+
6
+ const values = ref([]);
7
+ const model = defineModel({ default: [] });
8
+
9
+ function distinct(node) {
10
+ // 👀 use node traversal to get the parent node
11
+ const parent = node.at('$parent')
12
+ if (parent.value) {
13
+ // Ensure all the siblings are different values
14
+ for (const childName in parent.value) {
15
+ if (''+childName === ''+node.name) {
16
+ continue;
17
+ }
18
+ if (parent.value[childName] === node.value) {
19
+ return false;
20
+ }
21
+ }
22
+ }
23
+ return true
24
+ }
25
+
26
+ watch(values, (newValues) => {
27
+ model.value = newValues;
28
+ });
29
+ </script>
30
+
31
+ <template>
32
+ <div v-auto-animate>
33
+ <FormKit v-model="values" name="allowedValue" type="list" dynamic #default="{ items, node, value }">
34
+ <h5>Allowed Values
35
+ <button type="button" @click="values.push(null)" class="btn btn-sm btn-primary ms-3">
36
+ Add Value
37
+ </button>
38
+ </h5>
39
+ <p class="form-text">
40
+ An ordered list of allowed values. The values should be ordered from low to high as determined by the achievement creator.
41
+ </p>
42
+
43
+ <div class="ms-5 mb-3 p-3 border rounded col-md-8" v-if="items.length > 0">
44
+ <div v-for="(item, index) in items" :key="item" class="value-item">
45
+ <FormKit
46
+ type="innerLabelTextInput"
47
+ :index="index"
48
+ inner-class="input-group"
49
+ label-class="input-group-text"
50
+ :validation-rules="{ distinct }"
51
+ validation="required:trim|distinct"
52
+ :validation-messages="{
53
+ 'required': 'A value is required.',
54
+ 'distinct': 'The values must all be different.',
55
+ }"
56
+ outer-class="$reset"
57
+ :aria-label="'Allowed value '+(index+1)"
58
+ >
59
+ <template #label="context">
60
+ <label :class="context.classes.label">{{ index + 1 }}</label>
61
+ </template>
62
+ </FormKit>
63
+ <ul class="controls mt-2">
64
+ <li>
65
+ <button
66
+ type="button"
67
+ @click="values.splice(index - 1, 0, values.splice(index, 1)[0])"
68
+ class="button"
69
+ >
70
+ <FormKitIcon icon="arrowUp"/>
71
+ </button>
72
+ </li>
73
+ <li>
74
+ <button
75
+ type="button"
76
+ @click="values.splice(index + 1, 0, values.splice(index, 1)[0])"
77
+ class="button"
78
+ >
79
+ <FormKitIcon icon="arrowDown"/>
80
+ </button>
81
+ </li>
82
+ <li>
83
+ <button
84
+ type="button"
85
+ @click="values.splice(index, 1)"
86
+ class="button close"
87
+ >
88
+ <FormKitIcon icon="close"/>
89
+ </button>
90
+ </li>
91
+ </ul>
92
+ </div>
93
+ </div>
94
+ </FormKit>
95
+ </div>
96
+ </template>
97
+
98
+ <style scoped>
99
+ .value-item {
100
+ display: flex;
101
+ align-items: start;
102
+ margin-bottom: 0.5rem;
103
+ }
104
+
105
+ .value-item:deep(.formkit-outer) {
106
+ margin-bottom: 0;
107
+ flex-grow: 1;
108
+ }
109
+
110
+ .controls {
111
+ list-style-type: none;
112
+ margin: 0;
113
+ padding: 0;
114
+ display: flex;
115
+ align-items: center;
116
+ }
117
+
118
+ .controls .button {
119
+ border: none;
120
+ background: none;
121
+ padding: 0;
122
+ margin: 0;
123
+ cursor: pointer;
124
+ color: #999;
125
+ line-height: 1;
126
+ transition: color 0.3s ease;
127
+ appearance: none;
128
+ font-size: 1em;
129
+ color: var(--fk-color-primary);
130
+ margin-left: 0.5rem;
131
+ }
132
+
133
+ .controls:deep(svg) {
134
+ display: block;
135
+ width: 1em;
136
+ max-height: 1.25em;
137
+ height: auto;
138
+ fill: currentColor;
139
+ }
140
+
141
+ .controls .close {
142
+ color: var(--fk-color-danger);
143
+ }
144
+ </style>
@@ -0,0 +1,62 @@
1
+ import {
2
+ outer,
3
+ inner,
4
+ wrapper,
5
+ label,
6
+ help,
7
+ messages,
8
+ message,
9
+ icon,
10
+ prefix,
11
+ suffix,
12
+ textInput,
13
+ casts,
14
+ } from '@formkit/inputs'
15
+ /**
16
+ * Input definition for a text.
17
+ * @public
18
+ */
19
+ export const innerLabelTextInput = {
20
+ /**
21
+ * The actual schema of the input, or a function that returns the schema.
22
+ */
23
+ schema: outer(
24
+ wrapper(
25
+ inner(
26
+ label('$label'),
27
+ icon('prefix', 'label'),
28
+ prefix(),
29
+ textInput(),
30
+ suffix(),
31
+ icon('suffix')
32
+ )
33
+ ),
34
+ help('$help'),
35
+ messages(message('$message.value'))
36
+ ),
37
+ /**
38
+ * The type of node, can be a list, group, or input.
39
+ */
40
+ type: 'input',
41
+ /**
42
+ * The family of inputs this one belongs too. For example "text" and "email"
43
+ * are both part of the "text" family. This is primary used for styling.
44
+ */
45
+ family: 'text',
46
+ /**
47
+ * An array of extra props to accept for this input.
48
+ */
49
+ props: [],
50
+ /**
51
+ * Forces node.props.type to be this explicit value.
52
+ */
53
+ forceTypeProp: 'text',
54
+ /**
55
+ * Additional features that should be added to your input
56
+ */
57
+ features: [casts],
58
+ /**
59
+ * The key used to memoize the schema.
60
+ */
61
+ schemaMemoKey: 'qmwq6rtsiye',
62
+ }
@@ -0,0 +1,57 @@
1
+ import {
2
+ outer,
3
+ inner,
4
+ wrapper,
5
+ label,
6
+ help,
7
+ messages,
8
+ message,
9
+ prefix,
10
+ suffix,
11
+ icon,
12
+ textareaInput,
13
+ initialValue,
14
+ } from '@formkit/inputs'
15
+ /**
16
+ * Input definition for a textarea.
17
+ * @public
18
+ */
19
+ export const innerLabelTextareaInput = {
20
+ /**
21
+ * The actual schema of the input, or a function that returns the schema.
22
+ */
23
+ schema: outer(
24
+ wrapper(
25
+ inner(
26
+ label('$label'),
27
+ icon('prefix', 'label'),
28
+ prefix(),
29
+ textareaInput(),
30
+ suffix(),
31
+ icon('suffix')
32
+ )
33
+ ),
34
+ help('$help'),
35
+ messages(message('$message.value'))
36
+ ),
37
+ /**
38
+ * The type of node, can be a list, group, or input.
39
+ */
40
+ type: 'input',
41
+ /**
42
+ * An array of extra props to accept for this input.
43
+ */
44
+ props: [],
45
+ /**
46
+ * Forces node.props.type to be this explicit value.
47
+ */
48
+ forceTypeProp: 'textarea',
49
+ /**
50
+ * Additional features that should be added to your input
51
+ */
52
+ features: [initialValue],
53
+ /**
54
+ * The key used to memoize the schema.
55
+ */
56
+ schemaMemoKey: 'zq0nltggno',
57
+ }
@@ -0,0 +1,76 @@
1
+ import {
2
+ outer,
3
+ inner,
4
+ wrapper,
5
+ label,
6
+ help,
7
+ messages,
8
+ message,
9
+ prefix,
10
+ suffix,
11
+ icon,
12
+ selectInput,
13
+ option,
14
+ optionSlot,
15
+ optGroup,
16
+ $if,
17
+ options,
18
+ selects,
19
+ defaultIcon,
20
+ } from '@formkit/inputs'
21
+ /**
22
+ * Input definition for a select.
23
+ * @public
24
+ */
25
+ export const selectInputGroup = {
26
+ /**
27
+ * The actual schema of the input, or a function that returns the schema.
28
+ */
29
+ schema: outer(
30
+ wrapper(
31
+ inner(
32
+ label('$label'),
33
+ icon('prefix'),
34
+ prefix(),
35
+ selectInput(
36
+ $if(
37
+ '$slots.default',
38
+ () => '$slots.default',
39
+ optionSlot(
40
+ $if(
41
+ '$option.group',
42
+ optGroup(optionSlot(option('$option.label'))),
43
+ option('$option.label')
44
+ )
45
+ )
46
+ )
47
+ ),
48
+ $if('$attrs.multiple !== undefined', () => '', icon('select')),
49
+ suffix(),
50
+ icon('suffix')
51
+ )
52
+ ),
53
+ help('$help'),
54
+ messages(message('$message.value'))
55
+ ),
56
+ /**
57
+ * The type of node, can be a list, group, or input.
58
+ */
59
+ type: 'input',
60
+ /**
61
+ * An array of extra props to accept for this input.
62
+ */
63
+ props: ['options', 'placeholder', 'optionsLoader'],
64
+ /**
65
+ * Forces node.props.type to be this explicit value.
66
+ */
67
+ forceTypeProp: 'select',
68
+ /**
69
+ * Additional features that should be added to your input
70
+ */
71
+ features: [options, selects, defaultIcon('select', 'select')],
72
+ /**
73
+ * The key used to memoize the schema.
74
+ */
75
+ schemaMemoKey: 'at63zamx5wg',
76
+ }
package/src/main.js ADDED
@@ -0,0 +1,50 @@
1
+ //import "bootstrap/dist/css/bootstrap.min.css";
2
+ //import "bootstrap";
3
+ //import './assets/main.css'
4
+ //import './assets/style.scss';
5
+
6
+ import { createApp } from 'vue';
7
+ import App from './App.vue';
8
+ import { plugin, defaultConfig } from "@formkit/vue";
9
+ import customConfig from '../formkit.config.js';
10
+ import { innerLabelTextInput } from '@/inputs/innerLabelTextInput.js';
11
+ import { innerLabelTextareaInput } from '@/inputs/innerLabelTextareaInput.js';
12
+ import { selectInputGroup } from '@/inputs/selectInputGroup.js';
13
+
14
+ const createDefiner = (el, props) => {
15
+ const app = createApp(App, props);
16
+ app.use(plugin, defaultConfig({
17
+ config: customConfig.config,
18
+ inputs: {
19
+ innerLabelTextInput,
20
+ innerLabelTextareaInput,
21
+ selectInputGroup,
22
+ },
23
+ }));
24
+ return app;
25
+ }
26
+
27
+ window.addEventListener('ob3-open', function(event) {
28
+ const selector = event.detail?.selector || '#ob3-definer';
29
+ const mountEl = document.querySelector(selector);
30
+ if (!mountEl) {
31
+ throw new Error('No element found for selector ' + selector);
32
+ }
33
+ const props = { ...mountEl.dataset };
34
+ if (event.detail?.achievement) {
35
+ const achievement = event.detail.achievement;
36
+ if (typeof achievement === 'string') {
37
+ props.achievement = event.detail.achievement;
38
+ } else {
39
+ props.achievement = JSON.stringify(event.detail.achievement);
40
+ }
41
+ }
42
+ const app = createDefiner(selector, props);
43
+ app.mount(selector);
44
+ window.addEventListener('ob3-close', function close() {
45
+ window.removeEventListener('ob3-open', close);
46
+ app.unmount();
47
+ });
48
+ });
49
+
50
+ export default createDefiner;