contacts-pane 3.0.2 → 3.0.3
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/README.md +53 -1
- package/dist/contactsPane.js +6487 -763
- package/dist/contactsPane.js.map +1 -1
- package/dist/contactsPane.min.js +2 -0
- package/dist/contactsPane.min.js.map +1 -0
- package/dist/styles/contactsPane.css +602 -0
- package/dist/styles/contactsRDFFormsEnforced.css +513 -0
- package/dist/styles/groupMembership.css +115 -0
- package/dist/styles/individual.css +12 -0
- package/dist/styles/localUtils.css +49 -0
- package/dist/styles/mugshotGallery.css +17 -0
- package/dist/styles/toolsPane.css +43 -0
- package/dist/styles/utilities.css +69 -0
- package/dist/styles/webidControl.css +90 -0
- package/package.json +23 -17
- package/dist/autocompleteBar.d.ts +0 -3
- package/dist/autocompleteBar.d.ts.map +0 -1
- package/dist/autocompleteBar.js +0 -90
- package/dist/autocompleteBar.js.map +0 -1
- package/dist/autocompleteField.d.ts +0 -20
- package/dist/autocompleteField.d.ts.map +0 -1
- package/dist/autocompleteField.js +0 -165
- package/dist/autocompleteField.js.map +0 -1
- package/dist/autocompletePicker.d.ts +0 -15
- package/dist/autocompletePicker.d.ts.map +0 -1
- package/dist/autocompletePicker.js +0 -253
- package/dist/autocompletePicker.js.map +0 -1
- package/dist/contactLogic.js +0 -223
- package/dist/contactLogic.js.map +0 -1
- package/dist/groupMembershipControl.js +0 -107
- package/dist/groupMembershipControl.js.map +0 -1
- package/dist/individual.js +0 -115
- package/dist/individual.js.map +0 -1
- package/dist/mintNewAddressBook.js +0 -145
- package/dist/mintNewAddressBook.js.map +0 -1
- package/dist/mugshotGallery.js +0 -264
- package/dist/mugshotGallery.js.map +0 -1
- package/dist/publicData.d.ts +0 -82
- package/dist/publicData.d.ts.map +0 -1
- package/dist/publicData.js +0 -421
- package/dist/publicData.js.map +0 -1
- package/dist/toolsPane.js +0 -671
- package/dist/toolsPane.js.map +0 -1
- package/dist/webidControl.js +0 -320
- package/dist/webidControl.js.map +0 -1
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/* mugshotGallery.js styles — extracted from inline styles */
|
|
2
|
+
/* Uses CSS custom properties from the global stylesheet (dev-global.css / mashlib) */
|
|
3
|
+
|
|
4
|
+
/* ── Mugshot image ───────────────────────────────────────────── */
|
|
5
|
+
|
|
6
|
+
.contactPane .mugshotImage {
|
|
7
|
+
max-height: 10em;
|
|
8
|
+
border-radius: var(--border-radius-full);
|
|
9
|
+
margin: var(--spacing-sm);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.contactPane button:has(> img[src$=".svg"]) {
|
|
13
|
+
background-color: var(--color-section-bg) !important;
|
|
14
|
+
border: none !important;
|
|
15
|
+
margin: 0 !important;
|
|
16
|
+
border-radius: 0 !important;
|
|
17
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/* toolsPane.js styles — extracted from inline styles */
|
|
2
|
+
/* Uses CSS custom properties from the global stylesheet (dev-global.css / mashlib) */
|
|
3
|
+
|
|
4
|
+
/* ── Tools pane table ────────────────────────────────────────── */
|
|
5
|
+
|
|
6
|
+
.contactPane .statsLog {
|
|
7
|
+
font-size: var(--font-size-lg);
|
|
8
|
+
margin: var(--spacing-md);
|
|
9
|
+
background-color: var(--color-background);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.contactPane .statsLog pre {
|
|
13
|
+
padding: var(--spacing-md);
|
|
14
|
+
white-space: pre-wrap;
|
|
15
|
+
word-wrap: break-word;
|
|
16
|
+
overflow-wrap: break-word;
|
|
17
|
+
overflow: hidden;
|
|
18
|
+
max-width: 100%;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/* ── Tools pane layout ────────────────────────────────────────── */
|
|
22
|
+
|
|
23
|
+
.contactPane .toolsPane {
|
|
24
|
+
display: flex;
|
|
25
|
+
flex-direction: column;
|
|
26
|
+
gap: var(--spacing-xs);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.contactPane .toolsButtonsContainer {
|
|
30
|
+
display: flex;
|
|
31
|
+
flex-wrap: wrap;
|
|
32
|
+
gap: var(--spacing-xs);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/* ── Load index button states ──────────────────────────────── */
|
|
36
|
+
|
|
37
|
+
.contactPane .toolsButton--error {
|
|
38
|
+
background-color: var(--color-error);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.contactPane .toolsButton--success {
|
|
42
|
+
background-color: var(--color-primary);
|
|
43
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/* Shared utility variables for component styles.
|
|
2
|
+
These are kept here (instead of in dev-global.css) so they can be
|
|
3
|
+
bundled with component styles and reused consistently across the app.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/* Utility helper classes */
|
|
7
|
+
.hidden {
|
|
8
|
+
display: none !important;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.btn-primary {
|
|
12
|
+
min-height: var(--min-touch-target);
|
|
13
|
+
padding: var(--spacing-sm) var(--spacing-md);
|
|
14
|
+
border: 1px solid var(--color-primary);
|
|
15
|
+
border-radius: var(--border-radius-base);
|
|
16
|
+
background: var(--color-primary);
|
|
17
|
+
color: var(--color-background);
|
|
18
|
+
font-weight: 600;
|
|
19
|
+
cursor: pointer;
|
|
20
|
+
transition: all var(--animation-duration) ease;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.btn-primary:hover {
|
|
24
|
+
background: color-mix(in srgb, var(--color-primary) 90%, black);
|
|
25
|
+
box-shadow: var(--box-shadow-hover);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.btn-primary:active {
|
|
29
|
+
box-shadow: var(--box-shadow-active);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.btn-primary:disabled {
|
|
33
|
+
opacity: var(--opacity-disabled);
|
|
34
|
+
cursor: not-allowed;
|
|
35
|
+
transform: none;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.btn-secondary {
|
|
39
|
+
min-height: var(--min-touch-target);
|
|
40
|
+
padding: var(--spacing-sm) var(--spacing-md);
|
|
41
|
+
border: var(--border-width-thin) solid var(--color-secondary);
|
|
42
|
+
border-radius: var(--border-radius-base);
|
|
43
|
+
background: var(--color-secondary);
|
|
44
|
+
color: var(--color-background);
|
|
45
|
+
font-weight: var(--font-weight-bold);
|
|
46
|
+
cursor: pointer;
|
|
47
|
+
transition: all var(--animation-duration) ease;
|
|
48
|
+
text-decoration: none;
|
|
49
|
+
display: inline-flex;
|
|
50
|
+
align-items: center;
|
|
51
|
+
justify-content: center;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.btn-secondary:hover {
|
|
55
|
+
background: color-mix(in srgb, var(--color-secondary) 85%, black);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.btn-secondary:disabled {
|
|
59
|
+
opacity: var(--opacity-disabled);
|
|
60
|
+
cursor: not-allowed;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.action-button-focus:focus,
|
|
64
|
+
.action-button-focus:focus-visible {
|
|
65
|
+
outline: 3px solid var(--color-primary) !important;
|
|
66
|
+
outline-offset: 2px !important;
|
|
67
|
+
box-shadow: 0 0 0 2px var(--color-background), var(--box-shadow-focus) !important;
|
|
68
|
+
z-index: 1;
|
|
69
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/* ── Named pane (rendered sub-pane) ──────────────────────────── */
|
|
2
|
+
.contactPane .namedPane {
|
|
3
|
+
border: var(--border-width-sm) solid var(--color-text-muted);
|
|
4
|
+
border-radius: var(--border-radius-base);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
/* ── Persona row ─────────────────────────────────────────────── */
|
|
8
|
+
|
|
9
|
+
.contactPane .personaRow {
|
|
10
|
+
padding: var(--spacing-xs);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.contactPane .personaRow--webid,
|
|
14
|
+
.contactPane .personaRow--webid td,
|
|
15
|
+
.contactPane .personaRow--webid button,
|
|
16
|
+
.contactPane .personaRow--webid button:hover,
|
|
17
|
+
.contactPane .personaRow--webid .hoverControl:has(> img:first-child),
|
|
18
|
+
.contactPane .personaRow--webid .hoverControl:has(> img:first-child):hover,
|
|
19
|
+
.contactPane .personaRow--webid .personaOpenButton:has(> img:first-child),
|
|
20
|
+
.contactPane .personaRow--webid .personaOpenButton:has(> img:first-child):hover {
|
|
21
|
+
background-color: var(--color-info-bg) !important;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/* ── Full-width elements ─────────────────────────────────────── */
|
|
25
|
+
|
|
26
|
+
.contactPane .fullWidth {
|
|
27
|
+
width: 100%;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/* ── Open/close profile button ───────────────────────────────── */
|
|
31
|
+
|
|
32
|
+
.contactPane .personaOpenButton {
|
|
33
|
+
float: right;
|
|
34
|
+
background-color: transparent;
|
|
35
|
+
border: none;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/* hoverControl layout overrides are now enforced in contactsRDFFormsEnforced.css */
|
|
39
|
+
|
|
40
|
+
/* ── Delete confirmation popup in webidControl ───────────────── */
|
|
41
|
+
|
|
42
|
+
/* Remove intermediate positioned ancestor so popup anchors to .hoverControl */
|
|
43
|
+
.contactPane .webidControl div[style*="position: relative"]:has(> div[style*="display: grid"]) {
|
|
44
|
+
position: static !important;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/* Position the popup absolutely so it never participates in the flex row */
|
|
48
|
+
.contactPane .webidControl div[style*="position: relative"] > div[style*="display: grid"] {
|
|
49
|
+
position: absolute !important;
|
|
50
|
+
top: 0 !important;
|
|
51
|
+
right: 0 !important;
|
|
52
|
+
left: auto !important;
|
|
53
|
+
z-index: 9999 !important;
|
|
54
|
+
display: grid !important;
|
|
55
|
+
pointer-events: auto !important;
|
|
56
|
+
opacity: 1 !important;
|
|
57
|
+
visibility: visible !important;
|
|
58
|
+
padding: var(--spacing-btn) !important;
|
|
59
|
+
min-width: 12em !important;
|
|
60
|
+
background: var(--color-background) !important;
|
|
61
|
+
border: var(--border-width-sm) solid var(--color-primary) !important;
|
|
62
|
+
border-radius: var(--border-radius-base) !important;
|
|
63
|
+
box-shadow: var(--box-shadow-popup) !important;
|
|
64
|
+
grid-template-columns: auto auto !important;
|
|
65
|
+
gap: var(--spacing-xxs) !important;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/* ── Section heading ─────────────────────────────────────────── */
|
|
69
|
+
|
|
70
|
+
.contactPane .contactPanedHeading {
|
|
71
|
+
font-size: var(--font-size-lg);
|
|
72
|
+
font-weight: bold;
|
|
73
|
+
color: var(--color-primary);
|
|
74
|
+
margin: var(--spacing-sm) 0;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/* ── Prompt text ─────────────────────────────────────────────── */
|
|
78
|
+
|
|
79
|
+
.contactPane .webidPrompt {
|
|
80
|
+
padding: var(--spacing-sm);
|
|
81
|
+
border: none;
|
|
82
|
+
font-size: var(--font-size-base);
|
|
83
|
+
white-space: pre-wrap;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/* ── Visibility / display helpers ────────────────────────────── */
|
|
87
|
+
|
|
88
|
+
.contactPane .collapsed {
|
|
89
|
+
visibility: collapse;
|
|
90
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "contacts-pane",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.3",
|
|
4
4
|
"description": "Contacts Pane: Contacts manager for Address Book, Groups, and Individuals.",
|
|
5
5
|
"main": "dist/contactsPane.js",
|
|
6
6
|
"files": [
|
|
@@ -10,19 +10,17 @@
|
|
|
10
10
|
],
|
|
11
11
|
"scripts": {
|
|
12
12
|
"clean": "rm -rf dist",
|
|
13
|
-
"build": "npm run clean && npm run
|
|
14
|
-
"build-dist": "
|
|
15
|
-
"build-js": "babel src --out-dir dist --extensions '.ts,.js' --source-maps",
|
|
16
|
-
"build-types": "tsc --emitDeclarationOnly",
|
|
13
|
+
"build": "npm run clean && npm run build-dist",
|
|
14
|
+
"build-dist": "webpack --progress",
|
|
17
15
|
"lint": "eslint",
|
|
18
16
|
"lint-fix": "eslint --fix",
|
|
19
|
-
"typecheck": "tsc --noEmit",
|
|
20
17
|
"typecheck-test": "tsc --noEmit -p tsconfig.test.json",
|
|
21
18
|
"test": "jest --no-coverage",
|
|
22
19
|
"test-coverage": "jest --coverage",
|
|
23
20
|
"ignore:prepublishOnly": "npm run build && npm run lint && npm run test",
|
|
24
|
-
"preversion": "npm run lint && npm run
|
|
25
|
-
"ignore:postpublish": "git push origin main --follow-tags"
|
|
21
|
+
"preversion": "npm run lint && npm run test",
|
|
22
|
+
"ignore:postpublish": "git push origin main --follow-tags",
|
|
23
|
+
"start": "webpack serve --config webpack.dev.config.mjs --open"
|
|
26
24
|
},
|
|
27
25
|
"repository": {
|
|
28
26
|
"type": "git",
|
|
@@ -47,13 +45,10 @@
|
|
|
47
45
|
"url": "https://github.com/SolidOS/contacts-pane/issues"
|
|
48
46
|
},
|
|
49
47
|
"homepage": "https://github.com/SolidOS/contacts-pane",
|
|
50
|
-
"dependencies": {
|
|
51
|
-
"mime-types": "^3.0.2"
|
|
52
|
-
},
|
|
53
48
|
"peerDependencies": {
|
|
54
|
-
"rdflib": "^2.3.
|
|
55
|
-
"solid-logic": "^4.0.
|
|
56
|
-
"solid-ui": "^3.0.
|
|
49
|
+
"rdflib": "^2.3.6",
|
|
50
|
+
"solid-logic": "^4.0.6",
|
|
51
|
+
"solid-ui": "^3.0.5"
|
|
57
52
|
},
|
|
58
53
|
"devDependencies": {
|
|
59
54
|
"@babel/cli": "^7.28.6",
|
|
@@ -63,22 +58,33 @@
|
|
|
63
58
|
"@testing-library/jest-dom": "^6.9.1",
|
|
64
59
|
"@types/jest": "^30.0.0",
|
|
65
60
|
"@typescript-eslint/parser": "^8.53.1",
|
|
61
|
+
"axe-core": "^4.11.1",
|
|
66
62
|
"babel-jest": "^30.2.0",
|
|
67
63
|
"babel-loader": "^10.0.0",
|
|
68
64
|
"babel-plugin-inline-import": "^3.0.0",
|
|
65
|
+
"baseline-browser-mapping": "^2.9.19",
|
|
69
66
|
"buffer": "^6.0.3",
|
|
67
|
+
"copy-webpack-plugin": "^13.0.1",
|
|
68
|
+
"css-loader": "^7.1.3",
|
|
70
69
|
"eslint": "^9.39.2",
|
|
71
70
|
"eslint-plugin-import": "^2.32.0",
|
|
72
71
|
"globals": "^17.1.0",
|
|
72
|
+
"html-webpack-plugin": "^5.6.6",
|
|
73
73
|
"jest": "^30.2.0",
|
|
74
|
+
"jest-axe": "^10.0.0",
|
|
74
75
|
"jest-environment-jsdom": "^30.2.0",
|
|
75
76
|
"jest-fetch-mock": "^3.0.3",
|
|
76
|
-
"neostandard": "^0.
|
|
77
|
+
"neostandard": "^0.13.0",
|
|
78
|
+
"node-polyfill-webpack-plugin": "^4.1.0",
|
|
77
79
|
"pane-registry": "^3.0.1",
|
|
78
80
|
"rdflib": "^2.3.6",
|
|
79
81
|
"solid-logic": "^4.0.6",
|
|
80
|
-
"solid-ui": "^3.0.
|
|
82
|
+
"solid-ui": "^3.0.6",
|
|
83
|
+
"style-loader": "^4.0.0",
|
|
81
84
|
"typescript": "^5.9.3",
|
|
82
|
-
"typescript-transpile-only": "^0.0.4"
|
|
85
|
+
"typescript-transpile-only": "^0.0.4",
|
|
86
|
+
"webpack": "^5.0.0",
|
|
87
|
+
"webpack-cli": "^6.0.1",
|
|
88
|
+
"webpack-dev-server": "^5.2.3"
|
|
83
89
|
}
|
|
84
90
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"autocompleteBar.d.ts","sourceRoot":"","sources":["../src/autocompleteBar.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AAgBlC,wBAAsB,yBAAyB,CAAE,GAAG,EAAC,YAAY,EAC/D,MAAM,EAAC,SAAS,EAAE,OAAO,KAAA,EAAE,kBAAkB,KAAA,GAAG,OAAO,CAAC,WAAW,CAAC,CAqErE"}
|
package/dist/autocompleteBar.js
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.renderAutocompleteControl = renderAutocompleteControl;
|
|
7
|
-
var _solidLogic = require("solid-logic");
|
|
8
|
-
var _solidUi = require("solid-ui");
|
|
9
|
-
var _autocompletePicker = require("./autocompletePicker");
|
|
10
|
-
var _publicData = require("./publicData");
|
|
11
|
-
// The Control with decorations
|
|
12
|
-
|
|
13
|
-
// dbpediaParameters
|
|
14
|
-
|
|
15
|
-
const WEBID_NOUN = 'Solid ID';
|
|
16
|
-
const kb = _solidLogic.store;
|
|
17
|
-
|
|
18
|
-
// const AUTOCOMPLETE_THRESHOLD = 4 // don't check until this many characters typed
|
|
19
|
-
// const AUTOCOMPLETE_ROWS = 12 // 20?
|
|
20
|
-
|
|
21
|
-
const GREEN_PLUS = _solidUi.icons.iconBase + 'noun_34653_green.svg';
|
|
22
|
-
const SEARCH_ICON = _solidUi.icons.iconBase + 'noun_Search_875351.svg';
|
|
23
|
-
async function renderAutocompleteControl(dom, person, options, addOneIdAndRefresh) {
|
|
24
|
-
async function autoCompleteDone(object, _name) {
|
|
25
|
-
const webid = object.uri;
|
|
26
|
-
removeDecorated();
|
|
27
|
-
return addOneIdAndRefresh(person, webid);
|
|
28
|
-
}
|
|
29
|
-
async function greenButtonHandler(_event) {
|
|
30
|
-
const webid = await _solidUi.widgets.askName(dom, _solidLogic.store, creationArea, _solidUi.ns.vcard('url'), null, WEBID_NOUN);
|
|
31
|
-
if (!webid) {
|
|
32
|
-
return; // cancelled by user
|
|
33
|
-
}
|
|
34
|
-
return addOneIdAndRefresh(person, webid);
|
|
35
|
-
}
|
|
36
|
-
function removeDecorated() {
|
|
37
|
-
if (decoratedAutocomplete) {
|
|
38
|
-
creationArea.removeChild(decoratedAutocomplete);
|
|
39
|
-
decoratedAutocomplete = null;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
async function searchButtonHandler(_event) {
|
|
43
|
-
if (decoratedAutocomplete) {
|
|
44
|
-
creationArea.removeChild(decoratedAutocomplete);
|
|
45
|
-
decoratedAutocomplete = null;
|
|
46
|
-
} else {
|
|
47
|
-
decoratedAutocomplete = dom.createElement('div');
|
|
48
|
-
decoratedAutocomplete.setAttribute('style', 'display: flex; flex-flow: wrap;');
|
|
49
|
-
decoratedAutocomplete.appendChild(await (0, _autocompletePicker.renderAutoComplete)(dom, acOptions, autoCompleteDone));
|
|
50
|
-
decoratedAutocomplete.appendChild(acceptButton);
|
|
51
|
-
decoratedAutocomplete.appendChild(cancelButton);
|
|
52
|
-
creationArea.appendChild(decoratedAutocomplete);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
async function droppedURIHandler(uris) {
|
|
56
|
-
for (const webid of uris) {
|
|
57
|
-
// normally one but can be more than one
|
|
58
|
-
await addOneIdAndRefresh(person, webid);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
const queryParams = options.queryParameters || _publicData.wikidataParameters;
|
|
62
|
-
const acceptButton = _solidUi.widgets.continueButton(dom);
|
|
63
|
-
const cancelButton = _solidUi.widgets.cancelButton(dom, removeDecorated);
|
|
64
|
-
const klass = options.class;
|
|
65
|
-
const acOptions = {
|
|
66
|
-
queryParams,
|
|
67
|
-
class: klass,
|
|
68
|
-
acceptButton,
|
|
69
|
-
cancelButton
|
|
70
|
-
};
|
|
71
|
-
var decoratedAutocomplete = null;
|
|
72
|
-
// const { dom } = dataBrowserContext
|
|
73
|
-
options = options || {};
|
|
74
|
-
options.editable = kb.updater.editable(person.doc().uri, kb);
|
|
75
|
-
const creationArea = dom.createElement('div');
|
|
76
|
-
creationArea.setAttribute('style', 'display: flex; flex-flow: wrap;');
|
|
77
|
-
if (options.editable) {
|
|
78
|
-
// creationArea.appendChild(await renderAutoComplete(dom, options, autoCompleteDone)) wait for searchButton
|
|
79
|
-
creationArea.style.width = '100%';
|
|
80
|
-
const plus = creationArea.appendChild(_solidUi.widgets.button(dom, GREEN_PLUS, options.idNoun, greenButtonHandler));
|
|
81
|
-
_solidUi.widgets.makeDropTarget(plus, droppedURIHandler, null);
|
|
82
|
-
if (options.dbLookup) {
|
|
83
|
-
creationArea.appendChild(_solidUi.widgets.button(dom, SEARCH_ICON, options.idNoun, searchButtonHandler));
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
return creationArea;
|
|
87
|
-
} // renderAutocompleteControl
|
|
88
|
-
|
|
89
|
-
// ends
|
|
90
|
-
//# sourceMappingURL=autocompleteBar.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"autocompleteBar.js","names":["_solidLogic","require","_solidUi","_autocompletePicker","_publicData","WEBID_NOUN","kb","store","GREEN_PLUS","icons","iconBase","SEARCH_ICON","renderAutocompleteControl","dom","person","options","addOneIdAndRefresh","autoCompleteDone","object","_name","webid","uri","removeDecorated","greenButtonHandler","_event","widgets","askName","creationArea","ns","vcard","decoratedAutocomplete","removeChild","searchButtonHandler","createElement","setAttribute","appendChild","renderAutoComplete","acOptions","acceptButton","cancelButton","droppedURIHandler","uris","queryParams","queryParameters","wikidataParameters","continueButton","klass","class","editable","updater","doc","style","width","plus","button","idNoun","makeDropTarget","dbLookup"],"sources":["../src/autocompleteBar.ts"],"sourcesContent":["// The Control with decorations\n\nimport { NamedNode } from 'rdflib'\nimport { store } from 'solid-logic'\nimport { ns, widgets, icons } from 'solid-ui'\nimport { renderAutoComplete } from './autocompletePicker' // dbpediaParameters\nimport { wikidataParameters } from './publicData'\n\nconst WEBID_NOUN = 'Solid ID'\n\nconst kb = store\n\n// const AUTOCOMPLETE_THRESHOLD = 4 // don't check until this many characters typed\n// const AUTOCOMPLETE_ROWS = 12 // 20?\n\nconst GREEN_PLUS = icons.iconBase + 'noun_34653_green.svg'\nconst SEARCH_ICON = icons.iconBase + 'noun_Search_875351.svg'\n\nexport async function renderAutocompleteControl (dom:HTMLDocument,\n person:NamedNode, options, addOneIdAndRefresh): Promise<HTMLElement> {\n async function autoCompleteDone (object, _name) {\n const webid = object.uri\n removeDecorated()\n return addOneIdAndRefresh(person, webid)\n }\n\n async function greenButtonHandler (_event) {\n const webid = await widgets.askName(dom, store, creationArea, ns.vcard('url'), null, WEBID_NOUN)\n if (!webid) {\n return // cancelled by user\n }\n return addOneIdAndRefresh(person, webid)\n }\n function removeDecorated () {\n if (decoratedAutocomplete) {\n creationArea.removeChild(decoratedAutocomplete)\n decoratedAutocomplete = null\n }\n }\n async function searchButtonHandler (_event) {\n if (decoratedAutocomplete) {\n creationArea.removeChild(decoratedAutocomplete)\n decoratedAutocomplete = null\n } else {\n decoratedAutocomplete = dom.createElement('div')\n decoratedAutocomplete.setAttribute('style', 'display: flex; flex-flow: wrap;')\n decoratedAutocomplete.appendChild(await renderAutoComplete(dom, acOptions, autoCompleteDone))\n decoratedAutocomplete.appendChild(acceptButton)\n decoratedAutocomplete.appendChild(cancelButton)\n creationArea.appendChild(decoratedAutocomplete)\n }\n }\n\n async function droppedURIHandler (uris) {\n for (const webid of uris) { // normally one but can be more than one\n await addOneIdAndRefresh(person, webid)\n }\n }\n\n const queryParams = options.queryParameters || wikidataParameters\n const acceptButton = widgets.continueButton(dom)\n const cancelButton = widgets.cancelButton(dom, removeDecorated)\n const klass = options.class\n const acOptions = {\n queryParams,\n class: klass,\n acceptButton,\n cancelButton\n }\n\n var decoratedAutocomplete: HTMLDivElement | null = null\n // const { dom } = dataBrowserContext\n options = options || {}\n options.editable = kb.updater.editable(person.doc().uri, kb)\n\n const creationArea = dom.createElement('div')\n creationArea.setAttribute('style', 'display: flex; flex-flow: wrap;')\n\n if (options.editable) {\n // creationArea.appendChild(await renderAutoComplete(dom, options, autoCompleteDone)) wait for searchButton\n creationArea.style.width = '100%'\n const plus = creationArea.appendChild(widgets.button(dom, GREEN_PLUS, options.idNoun, greenButtonHandler))\n widgets.makeDropTarget(plus, droppedURIHandler, null)\n if (options.dbLookup) {\n creationArea.appendChild(widgets.button(dom, SEARCH_ICON, options.idNoun, searchButtonHandler))\n }\n }\n return creationArea\n} // renderAutocompleteControl\n\n// ends\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { BlankNode, NamedNode, Variable } from 'rdflib';
|
|
2
|
-
/**
|
|
3
|
-
* Render a autocomplete form field
|
|
4
|
-
*
|
|
5
|
-
* The same function is used for many similar one-value fields, with different
|
|
6
|
-
* regexps used to validate.
|
|
7
|
-
*
|
|
8
|
-
* @param dom The HTML Document object aka Document Object Model
|
|
9
|
-
* @param container If present, the created widget will be appended to this
|
|
10
|
-
* @param already A hash table of (form, subject) kept to prevent recursive forms looping
|
|
11
|
-
* @param subject The thing about which the form displays/edits data
|
|
12
|
-
* @param form The form or field to be rendered
|
|
13
|
-
* @param doc The web document in which the data is
|
|
14
|
-
* @param callbackFunction Called when data is changed?
|
|
15
|
-
*
|
|
16
|
-
* @returns The HTML widget created
|
|
17
|
-
*/
|
|
18
|
-
export declare function autocompleteField(// @@ are they allowed too be async??
|
|
19
|
-
dom: HTMLDocument, container: HTMLElement | undefined, already: any, subject: NamedNode | BlankNode | Variable, form: NamedNode, doc: NamedNode | undefined, callbackFunction: (ok: boolean, errorMessage: string) => void): HTMLElement;
|
|
20
|
-
//# sourceMappingURL=autocompleteField.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"autocompleteField.d.ts","sourceRoot":"","sources":["../src/autocompleteField.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAM,QAAQ,EAAE,MAAM,QAAQ,CAAA;AAQ3D;;;;;;;;;;;;;;;GAeG;AAEH,wBAAgB,iBAAiB,CAAG,qCAAqC;AACvE,GAAG,EAAE,YAAY,EACjB,SAAS,EAAE,WAAW,GAAG,SAAS,EAClC,OAAO,KAAA,EACP,OAAO,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,EACzC,IAAI,EAAE,SAAS,EACf,GAAG,EAAE,SAAS,GAAG,SAAS,EAC1B,gBAAgB,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,KAAK,IAAI,GAC5D,WAAW,CA2Ib"}
|
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.autocompleteField = autocompleteField;
|
|
7
|
-
var _rdflib = require("rdflib");
|
|
8
|
-
var _solidLogic = require("solid-logic");
|
|
9
|
-
var _solidUi = require("solid-ui");
|
|
10
|
-
var _autocompletePicker = require("./autocompletePicker");
|
|
11
|
-
/* Form field for doing autocompleete
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
// dbpediaParameters
|
|
15
|
-
|
|
16
|
-
// const AUTOCOMPLETE_THRESHOLD = 4 // don't check until this many characters typed
|
|
17
|
-
// const AUTOCOMPLETE_ROWS = 12 // 20?
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Render a autocomplete form field
|
|
21
|
-
*
|
|
22
|
-
* The same function is used for many similar one-value fields, with different
|
|
23
|
-
* regexps used to validate.
|
|
24
|
-
*
|
|
25
|
-
* @param dom The HTML Document object aka Document Object Model
|
|
26
|
-
* @param container If present, the created widget will be appended to this
|
|
27
|
-
* @param already A hash table of (form, subject) kept to prevent recursive forms looping
|
|
28
|
-
* @param subject The thing about which the form displays/edits data
|
|
29
|
-
* @param form The form or field to be rendered
|
|
30
|
-
* @param doc The web document in which the data is
|
|
31
|
-
* @param callbackFunction Called when data is changed?
|
|
32
|
-
*
|
|
33
|
-
* @returns The HTML widget created
|
|
34
|
-
*/
|
|
35
|
-
|
|
36
|
-
function autocompleteField(
|
|
37
|
-
// @@ are they allowed too be async??
|
|
38
|
-
dom, container, already, subject, form, doc, callbackFunction) {
|
|
39
|
-
async function addOneIdAndRefresh(result, _name) {
|
|
40
|
-
const ds = kb.statementsMatching(subject, property); // remove any multiple values
|
|
41
|
-
|
|
42
|
-
let is = ds.map(statement => (0, _rdflib.st)(statement.subject, statement.predicate, result, statement.why)); // can include >1 doc
|
|
43
|
-
if (is.length === 0) {
|
|
44
|
-
// or none
|
|
45
|
-
is = [(0, _rdflib.st)(subject, property, result, doc)];
|
|
46
|
-
}
|
|
47
|
-
try {
|
|
48
|
-
await kb.updater.updateMany(ds, is);
|
|
49
|
-
} catch (err) {
|
|
50
|
-
callbackFunction(false, err);
|
|
51
|
-
box.appendChild(_solidUi.widgets.errorMessageBlock(dom, 'Autocomplete form data write error:' + err));
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
callbackFunction(true, '');
|
|
55
|
-
}
|
|
56
|
-
const kb = _solidLogic.store;
|
|
57
|
-
const formDoc = form.doc ? form.doc() : null; // @@ if blank no way to know
|
|
58
|
-
|
|
59
|
-
const box = dom.createElement('tr');
|
|
60
|
-
if (container) container.appendChild(box);
|
|
61
|
-
const lhs = dom.createElement('td');
|
|
62
|
-
lhs.setAttribute('class', 'formFieldName');
|
|
63
|
-
lhs.setAttribute('style', ' vertical-align: middle;');
|
|
64
|
-
box.appendChild(lhs);
|
|
65
|
-
const rhs = dom.createElement('td');
|
|
66
|
-
rhs.setAttribute('class', 'formFieldValue');
|
|
67
|
-
box.appendChild(rhs);
|
|
68
|
-
const property = kb.any(form, _solidUi.ns.ui('property'));
|
|
69
|
-
if (!property) {
|
|
70
|
-
box.appendChild(dom.createTextNode('Error: No property given for autocomplete field: ' + form));
|
|
71
|
-
return box;
|
|
72
|
-
}
|
|
73
|
-
const searchClass = kb.any(form, _solidUi.ns.ui('searchClass'));
|
|
74
|
-
if (!searchClass) {
|
|
75
|
-
box.appendChild(dom.createTextNode('Error: No searchClass given for autocomplete field: ' + form));
|
|
76
|
-
return box;
|
|
77
|
-
}
|
|
78
|
-
const endPoint = kb.any(form, _solidUi.ns.ui('endPoint'));
|
|
79
|
-
if (!endPoint) {
|
|
80
|
-
box.appendChild(dom.createTextNode('Error: No SPARQL endPoint given for autocomplete field: ' + form));
|
|
81
|
-
return box;
|
|
82
|
-
}
|
|
83
|
-
const queryTemplate = kb.any(form, _solidUi.ns.ui('queryTemplate'));
|
|
84
|
-
if (!queryTemplate) {
|
|
85
|
-
box.appendChild(dom.createTextNode('Error: No queryTemplate given for autocomplete field: ' + form));
|
|
86
|
-
return box;
|
|
87
|
-
}
|
|
88
|
-
// It can be cleaner to just remove empty fields if you can't edit them anyway
|
|
89
|
-
const suppressEmptyUneditable = kb.anyJS(form, _solidUi.ns.ui('suppressEmptyUneditable'), null, formDoc);
|
|
90
|
-
lhs.appendChild(_solidUi.widgets.fieldLabel(dom, property, form));
|
|
91
|
-
const uri = _solidUi.widgets.mostSpecificClassURI(form);
|
|
92
|
-
let params = _solidUi.widgets.fieldParams[uri];
|
|
93
|
-
if (params === undefined) params = {}; // non-bottom field types can do this
|
|
94
|
-
// const theStyle = params.style || style.textInputStyle
|
|
95
|
-
const klass = kb.the(form, _solidUi.ns.ui('category'), null, formDoc);
|
|
96
|
-
/*
|
|
97
|
-
{ label: string;
|
|
98
|
-
logo: string;
|
|
99
|
-
searchByNameQuery?: string;
|
|
100
|
-
searchByNameURI?: string;
|
|
101
|
-
insitituteDetailsQuery?: string;
|
|
102
|
-
endPoint?: string;
|
|
103
|
-
class: object
|
|
104
|
-
}
|
|
105
|
-
*/
|
|
106
|
-
|
|
107
|
-
const searchByNameQuery = kb.the(form, _solidUi.ns.ui('searchByNameQuery'), null, formDoc);
|
|
108
|
-
if (!klass) {
|
|
109
|
-
box.appendChild(dom.createTextNode('Error: No class given for autocomplete field: ' + form));
|
|
110
|
-
return box;
|
|
111
|
-
}
|
|
112
|
-
const queryParams = {
|
|
113
|
-
label: 'from form',
|
|
114
|
-
logo: '',
|
|
115
|
-
class: klass,
|
|
116
|
-
endPoint: endPoint.value,
|
|
117
|
-
searchByNameQuery: searchByNameQuery?.value
|
|
118
|
-
};
|
|
119
|
-
const options = {
|
|
120
|
-
// cancelButton?: HTMLElement,
|
|
121
|
-
// acceptButton?: HTMLElement,
|
|
122
|
-
class: klass,
|
|
123
|
-
queryParams
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
// const acWiget = rhs.appendChild(await renderAutoComplete(dom, options, addOneIdAndRefresh))
|
|
127
|
-
|
|
128
|
-
// @@ set existing value is any
|
|
129
|
-
(0, _autocompletePicker.renderAutoComplete)(dom, options, addOneIdAndRefresh).then(acWiget => rhs.appendChild(acWiget));
|
|
130
|
-
const field = dom.createElement('input');
|
|
131
|
-
field.style = _solidUi.style.textInputStyle; // Do we have to override length etc?
|
|
132
|
-
rhs.appendChild(field);
|
|
133
|
-
field.setAttribute('type', params.type ? params.type : 'text');
|
|
134
|
-
const size = kb.any(form, _solidUi.ns.ui('size')); // Form has precedence
|
|
135
|
-
field.setAttribute('size', size ? '' + size : params.size ? '' + params.size : '20');
|
|
136
|
-
const maxLength = kb.any(form, _solidUi.ns.ui('maxLength'));
|
|
137
|
-
field.setAttribute('maxLength', maxLength ? '' + maxLength : '4096');
|
|
138
|
-
doc = doc || _solidUi.widgets.fieldStore(subject, property, doc);
|
|
139
|
-
let obj = kb.any(subject, property, undefined, doc);
|
|
140
|
-
if (!obj) {
|
|
141
|
-
obj = kb.any(form, _solidUi.ns.ui('default'));
|
|
142
|
-
}
|
|
143
|
-
if (obj) {
|
|
144
|
-
/* istanbul ignore next */
|
|
145
|
-
field.value = obj.value || obj.value || '';
|
|
146
|
-
}
|
|
147
|
-
field.setAttribute('style', _solidUi.style);
|
|
148
|
-
if (!kb.updater) {
|
|
149
|
-
throw new Error('kb has no updater');
|
|
150
|
-
}
|
|
151
|
-
if (!kb.updater.editable(doc.uri)) {
|
|
152
|
-
field.readOnly = true // was: disabled. readOnly is better
|
|
153
|
-
;
|
|
154
|
-
field.style = _solidUi.style.textInputStyleUneditable;
|
|
155
|
-
// backgroundColor = textInputBackgroundColorUneditable
|
|
156
|
-
if (suppressEmptyUneditable && field.value === '') {
|
|
157
|
-
box.style.display = 'none'; // clutter
|
|
158
|
-
}
|
|
159
|
-
return box;
|
|
160
|
-
}
|
|
161
|
-
return box;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// ends
|
|
165
|
-
//# sourceMappingURL=autocompleteField.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"autocompleteField.js","names":["_rdflib","require","_solidLogic","_solidUi","_autocompletePicker","autocompleteField","dom","container","already","subject","form","doc","callbackFunction","addOneIdAndRefresh","result","_name","ds","kb","statementsMatching","property","is","map","statement","st","predicate","why","length","updater","updateMany","err","box","appendChild","widgets","errorMessageBlock","store","formDoc","createElement","lhs","setAttribute","rhs","any","ns","ui","createTextNode","searchClass","endPoint","queryTemplate","suppressEmptyUneditable","anyJS","fieldLabel","uri","mostSpecificClassURI","params","fieldParams","undefined","klass","the","searchByNameQuery","queryParams","label","logo","class","value","options","renderAutoComplete","then","acWiget","field","style","textInputStyle","type","size","maxLength","fieldStore","obj","Error","editable","readOnly","textInputStyleUneditable","display"],"sources":["../src/autocompleteField.ts"],"sourcesContent":["/* Form field for doing autocompleete\n */\nimport { BlankNode, NamedNode, st, Variable } from 'rdflib'\nimport { store } from 'solid-logic'\nimport { ns, style, widgets } from 'solid-ui'\nimport { renderAutoComplete } from './autocompletePicker' // dbpediaParameters\n\n// const AUTOCOMPLETE_THRESHOLD = 4 // don't check until this many characters typed\n// const AUTOCOMPLETE_ROWS = 12 // 20?\n\n/**\n * Render a autocomplete form field\n *\n * The same function is used for many similar one-value fields, with different\n * regexps used to validate.\n *\n * @param dom The HTML Document object aka Document Object Model\n * @param container If present, the created widget will be appended to this\n * @param already A hash table of (form, subject) kept to prevent recursive forms looping\n * @param subject The thing about which the form displays/edits data\n * @param form The form or field to be rendered\n * @param doc The web document in which the data is\n * @param callbackFunction Called when data is changed?\n *\n * @returns The HTML widget created\n */\n\nexport function autocompleteField ( // @@ are they allowed too be async??\n dom: HTMLDocument,\n container: HTMLElement | undefined,\n already,\n subject: NamedNode | BlankNode | Variable,\n form: NamedNode,\n doc: NamedNode | undefined,\n callbackFunction: (ok: boolean, errorMessage: string) => void\n): HTMLElement {\n async function addOneIdAndRefresh (result, _name) {\n const ds = kb.statementsMatching(subject, property as any) // remove any multiple values\n\n let is = ds.map(statement => st(statement.subject, statement.predicate, result, statement.why)) // can include >1 doc\n if (is.length === 0) {\n // or none\n is = [st(subject, property as any, result, doc)]\n }\n try {\n await kb.updater.updateMany(ds, is)\n } catch (err) {\n callbackFunction(false, err)\n box.appendChild(widgets.errorMessageBlock(dom, 'Autocomplete form data write error:' + err))\n return\n }\n callbackFunction(true, '')\n }\n\n const kb = store\n const formDoc = form.doc ? form.doc() : null // @@ if blank no way to know\n\n const box = dom.createElement('tr')\n if (container) container.appendChild(box)\n const lhs = dom.createElement('td')\n lhs.setAttribute('class', 'formFieldName')\n lhs.setAttribute('style', ' vertical-align: middle;')\n box.appendChild(lhs)\n const rhs = dom.createElement('td')\n rhs.setAttribute('class', 'formFieldValue')\n box.appendChild(rhs)\n\n const property = kb.any(form, ns.ui('property'))\n if (!property) {\n box.appendChild(\n dom.createTextNode('Error: No property given for autocomplete field: ' + form)\n )\n return box\n }\n const searchClass = kb.any(form, ns.ui('searchClass'))\n if (!searchClass) {\n box.appendChild(\n dom.createTextNode('Error: No searchClass given for autocomplete field: ' + form)\n )\n return box\n }\n const endPoint = kb.any(form, ns.ui('endPoint'))\n if (!endPoint) {\n box.appendChild(\n dom.createTextNode('Error: No SPARQL endPoint given for autocomplete field: ' + form)\n )\n return box\n }\n const queryTemplate = kb.any(form, ns.ui('queryTemplate'))\n if (!queryTemplate) {\n box.appendChild(\n dom.createTextNode('Error: No queryTemplate given for autocomplete field: ' + form)\n )\n return box\n }\n // It can be cleaner to just remove empty fields if you can't edit them anyway\n const suppressEmptyUneditable = kb.anyJS(form, ns.ui('suppressEmptyUneditable'), null, formDoc)\n\n lhs.appendChild(widgets.fieldLabel(dom, property as any, form))\n const uri = widgets.mostSpecificClassURI(form)\n let params = widgets.fieldParams[uri]\n if (params === undefined) params = {} // non-bottom field types can do this\n // const theStyle = params.style || style.textInputStyle\n const klass = kb.the(form, ns.ui('category'), null, formDoc) as NamedNode\n /*\n { label: string;\n logo: string;\n searchByNameQuery?: string;\n searchByNameURI?: string;\n insitituteDetailsQuery?: string;\n endPoint?: string;\n class: object\n }\n*/\n\n const searchByNameQuery = kb.the(form, ns.ui('searchByNameQuery'), null, formDoc)\n\n if (!klass) {\n box.appendChild(\n dom.createTextNode('Error: No class given for autocomplete field: ' + form)\n )\n return box\n }\n\n const queryParams = { label: 'from form', logo: '', class: klass, endPoint: endPoint.value, searchByNameQuery: searchByNameQuery?.value }\n\n const options = { // cancelButton?: HTMLElement,\n // acceptButton?: HTMLElement,\n class: klass,\n queryParams\n }\n\n // const acWiget = rhs.appendChild(await renderAutoComplete(dom, options, addOneIdAndRefresh))\n\n // @@ set existing value is any\n renderAutoComplete(dom, options, addOneIdAndRefresh).then(acWiget => rhs.appendChild(acWiget))\n\n const field = dom.createElement('input')\n ;(field as any).style = style.textInputStyle // Do we have to override length etc?\n rhs.appendChild(field)\n field.setAttribute('type', params.type ? params.type : 'text')\n\n const size = kb.any(form, ns.ui('size')) // Form has precedence\n field.setAttribute(\n 'size',\n size ? '' + size : params.size ? '' + params.size : '20'\n )\n const maxLength = kb.any(form, ns.ui('maxLength'))\n field.setAttribute('maxLength', maxLength ? '' + maxLength : '4096')\n\n doc = doc || widgets.fieldStore(subject, property as any, doc)\n\n let obj = kb.any(subject, property as any, undefined, doc)\n if (!obj) {\n obj = kb.any(form, ns.ui('default'))\n }\n if (obj) {\n /* istanbul ignore next */\n field.value = obj.value || obj.value || ''\n }\n field.setAttribute('style', style)\n if (!kb.updater) {\n throw new Error('kb has no updater')\n }\n if (!kb.updater.editable((doc as NamedNode).uri)) {\n field.readOnly = true // was: disabled. readOnly is better\n ;(field as any).style = style.textInputStyleUneditable\n // backgroundColor = textInputBackgroundColorUneditable\n if (suppressEmptyUneditable && field.value === '') {\n box.style.display = 'none' // clutter\n }\n return box\n }\n return box\n}\n\n// ends\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { NamedNode } from 'rdflib';
|
|
2
|
-
import { QueryParameters } from './publicData';
|
|
3
|
-
type AutocompleteOptions = {
|
|
4
|
-
cancelButton?: HTMLElement;
|
|
5
|
-
acceptButton?: HTMLElement;
|
|
6
|
-
class: NamedNode;
|
|
7
|
-
queryParams: QueryParameters;
|
|
8
|
-
};
|
|
9
|
-
interface Callback1 {
|
|
10
|
-
(subject: NamedNode, name: string): void;
|
|
11
|
-
}
|
|
12
|
-
export declare function renderAutoComplete(dom: HTMLDocument, options: AutocompleteOptions, // subject:NamedNode, predicate:NamedNode,
|
|
13
|
-
callback: Callback1): Promise<HTMLDivElement>;
|
|
14
|
-
export {};
|
|
15
|
-
//# sourceMappingURL=autocompletePicker.d.ts.map
|