@adminforth/list-in-place-edit 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.
@@ -0,0 +1,13 @@
1
+
2
+ #!/bin/bash
3
+
4
+ # write npm run output both to console and to build.log
5
+ npm run build 2>&1 | tee build.log
6
+ build_status=${PIPESTATUS[0]}
7
+
8
+ # if exist status from the npm run build is not 0
9
+ # then exit with the status code from the npm run build
10
+ if [ $build_status -ne 0 ]; then
11
+ echo "Build failed. Exiting with status code $build_status"
12
+ exit $build_status
13
+ fi
@@ -0,0 +1,44 @@
1
+ #!/bin/sh
2
+
3
+ set -x
4
+
5
+ COMMIT_SHORT_SHA=$(echo $CI_COMMIT_SHA | cut -c1-8)
6
+
7
+
8
+ if [ "$CI_STEP_STATUS" = "success" ]; then
9
+ MESSAGE="Did a build without issues on \`$CI_REPO_NAME/$CI_COMMIT_BRANCH\`. Commit: _${CI_COMMIT_MESSAGE}_ (<$CI_COMMIT_URL|$COMMIT_SHORT_SHA>)"
10
+
11
+ curl -s -X POST -H "Content-Type: application/json" -d '{
12
+ "username": "'"$CI_COMMIT_AUTHOR"'",
13
+ "icon_url": "'"$CI_COMMIT_AUTHOR_AVATAR"'",
14
+ "attachments": [
15
+ {
16
+ "mrkdwn_in": ["text", "pretext"],
17
+ "color": "#36a64f",
18
+ "text": "'"$MESSAGE"'"
19
+ }
20
+ ]
21
+ }' "$DEVELOPERS_SLACK_WEBHOOK"
22
+ exit 0
23
+ fi
24
+ export BUILD_LOG=$(cat ./build.log)
25
+
26
+ BUILD_LOG=$(echo $BUILD_LOG | sed 's/"/\\"/g')
27
+
28
+ MESSAGE="Broke \`$CI_REPO_NAME/$CI_COMMIT_BRANCH\` with commit _${CI_COMMIT_MESSAGE}_ (<$CI_COMMIT_URL|$COMMIT_SHORT_SHA>)"
29
+ CODE_BLOCK="\`\`\`$BUILD_LOG\n\`\`\`"
30
+
31
+ echo "Sending slack message to developers $MESSAGE"
32
+ # Send the message
33
+ curl -sS -X POST -H "Content-Type: application/json" -d '{
34
+ "username": "'"$CI_COMMIT_AUTHOR"'",
35
+ "icon_url": "'"$CI_COMMIT_AUTHOR_AVATAR"'",
36
+ "attachments": [
37
+ {
38
+ "mrkdwn_in": ["text", "pretext"],
39
+ "color": "#8A1C12",
40
+ "text": "'"$CODE_BLOCK"'",
41
+ "pretext": "'"$MESSAGE"'"
42
+ }
43
+ ]
44
+ }' "$DEVELOPERS_SLACK_WEBHOOK" 2>&1
@@ -0,0 +1,42 @@
1
+ clone:
2
+ git:
3
+ image: woodpeckerci/plugin-git
4
+ settings:
5
+ partial: false
6
+ depth: 5
7
+
8
+ steps:
9
+ init-secrets:
10
+ when:
11
+ - event: push
12
+ image: infisical/cli
13
+ environment:
14
+ INFISICAL_TOKEN:
15
+ from_secret: VAULT_TOKEN
16
+ commands:
17
+ - infisical export --domain https://vault.devforth.io/api --format=dotenv-export --env="prod" > /woodpecker/deploy.vault.env
18
+ secrets:
19
+ - VAULT_TOKEN
20
+
21
+ release:
22
+ image: node:20
23
+ when:
24
+ - event: push
25
+ commands:
26
+ - apt update && apt install -y rsync
27
+ - export $(cat /woodpecker/deploy.vault.env | xargs)
28
+ - npm clean-install
29
+ - /bin/bash ./.woodpecker/buildRelease.sh
30
+ - npm audit signatures
31
+ - npx semantic-release
32
+
33
+ slack-on-failure:
34
+ when:
35
+ - event: push
36
+ status: [failure, success]
37
+ - event: push
38
+ image: curlimages/curl
39
+ commands:
40
+ - export $(cat /woodpecker/deploy.vault.env | xargs)
41
+ - /bin/sh ./.woodpecker/buildSlackNotify.sh
42
+
package/build.log ADDED
@@ -0,0 +1,11 @@
1
+
2
+ > @adminforth/list-in-place-edit@1.0.2 build
3
+ > tsc && rsync -av --exclude 'node_modules' custom dist/
4
+
5
+ sending incremental file list
6
+ custom/
7
+ custom/InPlaceEdit.vue
8
+ custom/tsconfig.json
9
+
10
+ sent 4,900 bytes received 58 bytes 9,916.00 bytes/sec
11
+ total size is 4,685 speedup is 0.94
@@ -0,0 +1,137 @@
1
+ <template>
2
+ <div class="relative group flex items-center" @click.stop>
3
+ <!-- Normal value display -->
4
+ <div v-if="!isEditing" class="flex items-center">
5
+ <ValueRenderer :column="column" :record="record" />
6
+ <button
7
+ v-if="!column.editReadonly"
8
+ @click="startEdit"
9
+ class="ml-2 opacity-0 group-hover:opacity-100 transition-opacity"
10
+ >
11
+ <IconPenSolid class="w-5 h-5 text-gray-400 hover:text-gray-600 dark:text-gray-500 dark:hover:text-gray-300"/>
12
+ </button>
13
+ </div>
14
+
15
+ <!-- Edit mode -->
16
+ <div v-else class="flex items-center min-w-full max-w-full gap-2">
17
+ <ColumnValueInputWrapper
18
+ ref="input"
19
+ :source="'edit'"
20
+ :column="column"
21
+ :currentValues="currentValues"
22
+ :mode="mode"
23
+ :columnOptions="columnOptions"
24
+ :unmasked="unmasked"
25
+ :setCurrentValue="setCurrentValue"
26
+ />
27
+ <div class="flex gap-1">
28
+ <button
29
+ @click="saveEdit"
30
+ :disabled="saving"
31
+ class="text-green-600 hover:text-green-700 dark:text-green-500 dark:hover:text-green-400"
32
+ >
33
+ <IconCheckOutline class="w-5 h-5" />
34
+ </button>
35
+ <button
36
+ @click="cancelEdit"
37
+ :disabled="saving"
38
+ class="text-red-600 hover:text-red-700 dark:text-red-500 dark:hover:text-red-400"
39
+ >
40
+ <IconXOutline class="w-5 h-5" />
41
+ </button>
42
+ </div>
43
+ </div>
44
+ </div>
45
+ </template>
46
+
47
+ <script setup lang="ts">
48
+ import { ref } from 'vue';
49
+ import { IconPenSolid, IconCheckOutline, IconXOutline } from '@iconify-prerendered/vue-flowbite';
50
+ import { callAdminForthApi } from '@/utils';
51
+ import { showErrorTost, showSuccesTost } from '@/composables/useFrontendApi';
52
+ import ValueRenderer from '@/components/ValueRenderer.vue';
53
+ import ColumnValueInputWrapper from '@/components/ColumnValueInputWrapper.vue';
54
+
55
+ const props = defineProps(['column', 'record', 'resource', 'adminUser', 'meta']);
56
+ const isEditing = ref(false);
57
+ const editValue = ref(null);
58
+ const saving = ref(false);
59
+ const input = ref(null);
60
+ const columnOptions = ref({});
61
+ const mode = ref('edit');
62
+ const currentValues = ref({});
63
+ const unmasked = ref({});
64
+
65
+ function startEdit() {
66
+ const value = props.record[props.column.name];
67
+ currentValues.value = {
68
+ [props.column.name]: props.column.isArray?.enabled
69
+ ? (Array.isArray(value) ? value : [value]).filter(v => v !== null && v !== undefined)
70
+ : value
71
+ };
72
+ isEditing.value = true;
73
+ }
74
+
75
+ function cancelEdit() {
76
+ isEditing.value = false;
77
+ editValue.value = null;
78
+ }
79
+
80
+ function setCurrentValue(field, value, arrayIndex = undefined) {
81
+ if (arrayIndex !== undefined && props.column.isArray?.enabled) {
82
+ // Handle array updates
83
+ if (!Array.isArray(currentValues.value[field])) {
84
+ currentValues.value[field] = [];
85
+ }
86
+
87
+ const newArray = [...currentValues.value[field]];
88
+
89
+ if (arrayIndex >= newArray.length) {
90
+ // When adding a new item, always add null
91
+ newArray.push(null);
92
+ } else {
93
+ // For existing items, handle type conversion
94
+ if (props.column.isArray?.itemType && ['integer', 'float', 'decimal'].includes(props.column.isArray.itemType)) {
95
+ newArray[arrayIndex] = value !== null && value !== '' ? +value : null;
96
+ } else {
97
+ newArray[arrayIndex] = value;
98
+ }
99
+ }
100
+
101
+ // Assign the new array
102
+ currentValues.value[field] = newArray;
103
+ editValue.value = newArray;
104
+ } else {
105
+ // Handle non-array updates
106
+ currentValues.value[field] = value;
107
+ editValue.value = value;
108
+ }
109
+ }
110
+
111
+ async function saveEdit() {
112
+ saving.value = true;
113
+ try {
114
+ const result = await callAdminForthApi({
115
+ method: 'POST',
116
+ path: `/plugin/${props.meta.pluginInstanceId}/update-field`,
117
+ body: {
118
+ resourceId: props.resource.resourceId,
119
+ recordId: props.record._primaryKeyValue,
120
+ field: props.column.name,
121
+ value: currentValues.value[props.column.name]
122
+ }
123
+ });
124
+
125
+ if (result.error) {
126
+ showErrorTost(result.error);
127
+ return;
128
+ }
129
+
130
+ showSuccesTost('Field updated successfully');
131
+ props.record[props.column.name] = currentValues.value[props.column.name];
132
+ isEditing.value = false;
133
+ } finally {
134
+ saving.value = false;
135
+ }
136
+ }
137
+ </script>
@@ -0,0 +1,19 @@
1
+ {
2
+ "compilerOptions": {
3
+ "baseUrl": ".", // This should point to your project root
4
+ "paths": {
5
+ "@/*": [
6
+ // "node_modules/adminforth/dist/spa/src/*"
7
+ "../../../spa/src/*"
8
+ ],
9
+ "*": [
10
+ // "node_modules/adminforth/dist/spa/node_modules/*"
11
+ "../../../spa/node_modules/*"
12
+ ],
13
+ "@@/*": [
14
+ // "node_modules/adminforth/dist/spa/src/*"
15
+ "."
16
+ ]
17
+ }
18
+ }
19
+ }
@@ -0,0 +1,137 @@
1
+ <template>
2
+ <div class="relative group flex items-center" @click.stop>
3
+ <!-- Normal value display -->
4
+ <div v-if="!isEditing" class="flex items-center">
5
+ <ValueRenderer :column="column" :record="record" />
6
+ <button
7
+ v-if="!column.editReadonly"
8
+ @click="startEdit"
9
+ class="ml-2 opacity-0 group-hover:opacity-100 transition-opacity"
10
+ >
11
+ <IconPenSolid class="w-5 h-5 text-gray-400 hover:text-gray-600 dark:text-gray-500 dark:hover:text-gray-300"/>
12
+ </button>
13
+ </div>
14
+
15
+ <!-- Edit mode -->
16
+ <div v-else class="flex items-center min-w-full max-w-full gap-2">
17
+ <ColumnValueInputWrapper
18
+ ref="input"
19
+ :source="'edit'"
20
+ :column="column"
21
+ :currentValues="currentValues"
22
+ :mode="mode"
23
+ :columnOptions="columnOptions"
24
+ :unmasked="unmasked"
25
+ :setCurrentValue="setCurrentValue"
26
+ />
27
+ <div class="flex gap-1">
28
+ <button
29
+ @click="saveEdit"
30
+ :disabled="saving"
31
+ class="text-green-600 hover:text-green-700 dark:text-green-500 dark:hover:text-green-400"
32
+ >
33
+ <IconCheckOutline class="w-5 h-5" />
34
+ </button>
35
+ <button
36
+ @click="cancelEdit"
37
+ :disabled="saving"
38
+ class="text-red-600 hover:text-red-700 dark:text-red-500 dark:hover:text-red-400"
39
+ >
40
+ <IconXOutline class="w-5 h-5" />
41
+ </button>
42
+ </div>
43
+ </div>
44
+ </div>
45
+ </template>
46
+
47
+ <script setup lang="ts">
48
+ import { ref } from 'vue';
49
+ import { IconPenSolid, IconCheckOutline, IconXOutline } from '@iconify-prerendered/vue-flowbite';
50
+ import { callAdminForthApi } from '@/utils';
51
+ import { showErrorTost, showSuccesTost } from '@/composables/useFrontendApi';
52
+ import ValueRenderer from '@/components/ValueRenderer.vue';
53
+ import ColumnValueInputWrapper from '@/components/ColumnValueInputWrapper.vue';
54
+
55
+ const props = defineProps(['column', 'record', 'resource', 'adminUser', 'meta']);
56
+ const isEditing = ref(false);
57
+ const editValue = ref(null);
58
+ const saving = ref(false);
59
+ const input = ref(null);
60
+ const columnOptions = ref({});
61
+ const mode = ref('edit');
62
+ const currentValues = ref({});
63
+ const unmasked = ref({});
64
+
65
+ function startEdit() {
66
+ const value = props.record[props.column.name];
67
+ currentValues.value = {
68
+ [props.column.name]: props.column.isArray?.enabled
69
+ ? (Array.isArray(value) ? value : [value]).filter(v => v !== null && v !== undefined)
70
+ : value
71
+ };
72
+ isEditing.value = true;
73
+ }
74
+
75
+ function cancelEdit() {
76
+ isEditing.value = false;
77
+ editValue.value = null;
78
+ }
79
+
80
+ function setCurrentValue(field, value, arrayIndex = undefined) {
81
+ if (arrayIndex !== undefined && props.column.isArray?.enabled) {
82
+ // Handle array updates
83
+ if (!Array.isArray(currentValues.value[field])) {
84
+ currentValues.value[field] = [];
85
+ }
86
+
87
+ const newArray = [...currentValues.value[field]];
88
+
89
+ if (arrayIndex >= newArray.length) {
90
+ // When adding a new item, always add null
91
+ newArray.push(null);
92
+ } else {
93
+ // For existing items, handle type conversion
94
+ if (props.column.isArray?.itemType && ['integer', 'float', 'decimal'].includes(props.column.isArray.itemType)) {
95
+ newArray[arrayIndex] = value !== null && value !== '' ? +value : null;
96
+ } else {
97
+ newArray[arrayIndex] = value;
98
+ }
99
+ }
100
+
101
+ // Assign the new array
102
+ currentValues.value[field] = newArray;
103
+ editValue.value = newArray;
104
+ } else {
105
+ // Handle non-array updates
106
+ currentValues.value[field] = value;
107
+ editValue.value = value;
108
+ }
109
+ }
110
+
111
+ async function saveEdit() {
112
+ saving.value = true;
113
+ try {
114
+ const result = await callAdminForthApi({
115
+ method: 'POST',
116
+ path: `/plugin/${props.meta.pluginInstanceId}/update-field`,
117
+ body: {
118
+ resourceId: props.resource.resourceId,
119
+ recordId: props.record._primaryKeyValue,
120
+ field: props.column.name,
121
+ value: currentValues.value[props.column.name]
122
+ }
123
+ });
124
+
125
+ if (result.error) {
126
+ showErrorTost(result.error);
127
+ return;
128
+ }
129
+
130
+ showSuccesTost('Field updated successfully');
131
+ props.record[props.column.name] = currentValues.value[props.column.name];
132
+ isEditing.value = false;
133
+ } finally {
134
+ saving.value = false;
135
+ }
136
+ }
137
+ </script>
@@ -0,0 +1,19 @@
1
+ {
2
+ "compilerOptions": {
3
+ "baseUrl": ".", // This should point to your project root
4
+ "paths": {
5
+ "@/*": [
6
+ // "node_modules/adminforth/dist/spa/src/*"
7
+ "../../../spa/src/*"
8
+ ],
9
+ "*": [
10
+ // "node_modules/adminforth/dist/spa/node_modules/*"
11
+ "../../../spa/node_modules/*"
12
+ ],
13
+ "@@/*": [
14
+ // "node_modules/adminforth/dist/spa/src/*"
15
+ "."
16
+ ]
17
+ }
18
+ }
19
+ }
package/dist/index.js ADDED
@@ -0,0 +1,80 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { AdminForthPlugin } from "adminforth";
11
+ export default class ListInPlaceEditPlugin extends AdminForthPlugin {
12
+ constructor(options) {
13
+ super(options, import.meta.url);
14
+ this.options = options;
15
+ }
16
+ modifyResourceConfig(adminforth, resourceConfig) {
17
+ const _super = Object.create(null, {
18
+ modifyResourceConfig: { get: () => super.modifyResourceConfig }
19
+ });
20
+ return __awaiter(this, void 0, void 0, function* () {
21
+ _super.modifyResourceConfig.call(this, adminforth, resourceConfig);
22
+ const targetColumns = resourceConfig.columns.filter(col => this.options.columns.includes(col.name));
23
+ targetColumns.forEach(column => {
24
+ var _a;
25
+ if ((_a = column.components) === null || _a === void 0 ? void 0 : _a.list) {
26
+ throw new Error(`Column ${column.name} already has a list component defined. ListInplaceEdit plugin cannot be used on columns that already have list components.`);
27
+ }
28
+ if (!column.components) {
29
+ column.components = {};
30
+ }
31
+ column.components.list = {
32
+ file: this.componentPath('InPlaceEdit.vue'),
33
+ meta: {
34
+ pluginInstanceId: this.pluginInstanceId,
35
+ columnName: column.name
36
+ }
37
+ };
38
+ });
39
+ });
40
+ }
41
+ validateConfigAfterDiscover(adminforth, resourceConfig) {
42
+ // Validate that columns exist if specific columns were specified
43
+ this.options.columns.forEach(colName => {
44
+ if (!resourceConfig.columns.find(c => c.name === colName)) {
45
+ throw new Error(`Column ${colName} specified in ListInplaceEdit plugin not found in resource ${resourceConfig.label}`);
46
+ }
47
+ });
48
+ }
49
+ instanceUniqueRepresentation(pluginOptions) {
50
+ return 'single';
51
+ }
52
+ setupEndpoints(server) {
53
+ // Add endpoint to update single field
54
+ server.endpoint({
55
+ method: 'POST',
56
+ path: `/plugin/${this.pluginInstanceId}/update-field`,
57
+ handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser }) {
58
+ const { resourceId, recordId, field, value } = body;
59
+ const resource = this.adminforth.config.resources.find(r => r.resourceId === resourceId);
60
+ // Create update object with just the single field
61
+ const updateRecord = { [field]: value };
62
+ // Use AdminForth's built-in update method
63
+ const connector = this.adminforth.connectors[resource.dataSource];
64
+ const oldRecord = yield connector.getRecordByPrimaryKey(resource, recordId);
65
+ const result = yield this.adminforth.updateResourceRecord({
66
+ resource,
67
+ recordId,
68
+ record: updateRecord,
69
+ oldRecord,
70
+ adminUser
71
+ });
72
+ if (result.error) {
73
+ return { error: result.error };
74
+ }
75
+ const updatedRecord = yield connector.getRecordByPrimaryKey(resource, recordId);
76
+ return { record: updatedRecord };
77
+ })
78
+ });
79
+ }
80
+ }
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
package/index.ts ADDED
@@ -0,0 +1,83 @@
1
+ import { AdminForthPlugin } from "adminforth";
2
+ import type { IAdminForth, IHttpServer, AdminForthResourcePages, AdminForthResourceColumn, AdminForthDataTypes, AdminForthResource } from "adminforth";
3
+ import type { PluginOptions } from './types.js';
4
+
5
+ export default class ListInPlaceEditPlugin extends AdminForthPlugin {
6
+ options: PluginOptions;
7
+
8
+ constructor(options: PluginOptions) {
9
+ super(options, import.meta.url);
10
+ this.options = options;
11
+ }
12
+
13
+ async modifyResourceConfig(adminforth: IAdminForth, resourceConfig: AdminForthResource) {
14
+ super.modifyResourceConfig(adminforth, resourceConfig);
15
+
16
+ const targetColumns = resourceConfig.columns.filter(col =>
17
+ this.options.columns.includes(col.name)
18
+ );
19
+
20
+ targetColumns.forEach(column => {
21
+ if (column.components?.list) {
22
+ throw new Error(`Column ${column.name} already has a list component defined. ListInplaceEdit plugin cannot be used on columns that already have list components.`);
23
+ }
24
+
25
+ if (!column.components) {
26
+ column.components = {};
27
+ }
28
+ column.components.list = {
29
+ file: this.componentPath('InPlaceEdit.vue'),
30
+ meta: {
31
+ pluginInstanceId: this.pluginInstanceId,
32
+ columnName: column.name
33
+ }
34
+ };
35
+ });
36
+ }
37
+
38
+ validateConfigAfterDiscover(adminforth: IAdminForth, resourceConfig: AdminForthResource) {
39
+ // Validate that columns exist if specific columns were specified
40
+ this.options.columns.forEach(colName => {
41
+ if (!resourceConfig.columns.find(c => c.name === colName)) {
42
+ throw new Error(`Column ${colName} specified in ListInplaceEdit plugin not found in resource ${resourceConfig.label}`);
43
+ }
44
+ });
45
+ }
46
+
47
+ instanceUniqueRepresentation(pluginOptions: any): string {
48
+ return 'single';
49
+ }
50
+
51
+ setupEndpoints(server: IHttpServer) {
52
+ // Add endpoint to update single field
53
+ server.endpoint({
54
+ method: 'POST',
55
+ path: `/plugin/${this.pluginInstanceId}/update-field`,
56
+ handler: async ({ body, adminUser }) => {
57
+ const { resourceId, recordId, field, value } = body;
58
+
59
+ const resource = this.adminforth.config.resources.find(r => r.resourceId === resourceId);
60
+ // Create update object with just the single field
61
+ const updateRecord = { [field]: value };
62
+
63
+ // Use AdminForth's built-in update method
64
+ const connector = this.adminforth.connectors[resource.dataSource];
65
+ const oldRecord = await connector.getRecordByPrimaryKey(resource, recordId)
66
+ const result = await this.adminforth.updateResourceRecord({
67
+ resource,
68
+ recordId,
69
+ record: updateRecord,
70
+ oldRecord,
71
+ adminUser
72
+ });
73
+
74
+ if (result.error) {
75
+ return { error: result.error };
76
+ }
77
+
78
+ const updatedRecord = await connector.getRecordByPrimaryKey(resource, recordId);
79
+ return { record: updatedRecord };
80
+ }
81
+ });
82
+ }
83
+ }
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@adminforth/list-in-place-edit",
3
+ "version": "1.0.0",
4
+ "main": "dist/index.js",
5
+ "types": "dist/index.d.ts",
6
+ "type": "module",
7
+ "scripts": {
8
+ "build": "tsc && rsync -av --exclude 'node_modules' custom dist/",
9
+ "prepare": "npm link adminforth"
10
+ },
11
+ "publishConfig": {
12
+ "access": "public"
13
+ },
14
+ "keywords": [
15
+ "adminforth"
16
+ ],
17
+ "author": "devforth",
18
+ "license": "MIT",
19
+ "description": "AdminForth List In Place Edit Plugin",
20
+ "devDependencies": {
21
+ "@types/node": "^22.10.7",
22
+ "semantic-release": "^24.2.1",
23
+ "semantic-release-slack-bot": "^4.0.2",
24
+ "typescript": "^5.7.3"
25
+ },
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "https://github.com/devforth/adminforth-list-in-place-edit"
29
+ },
30
+ "dependencies": {
31
+ "adminforth": "latest"
32
+ },
33
+ "release": {
34
+ "plugins": [
35
+ "@semantic-release/commit-analyzer",
36
+ "@semantic-release/release-notes-generator",
37
+ "@semantic-release/npm",
38
+ "@semantic-release/github",
39
+ [
40
+ "semantic-release-slack-bot",
41
+ {
42
+ "notifyOnSuccess": true,
43
+ "notifyOnFail": true,
44
+ "slackIcon": ":package:",
45
+ "markdownReleaseNotes": true
46
+ }
47
+ ]
48
+ ],
49
+ "branches": [
50
+ "main",
51
+ {
52
+ "name": "next",
53
+ "prerelease": true
54
+ }
55
+ ]
56
+ }
57
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,13 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include*/
4
+ "module": "node16", /* Specify what module code is generated. */
5
+ "outDir": "./dist", /* Specify an output folder for all emitted files. */
6
+ "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. */
7
+ "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
8
+ "strict": false, /* Enable all strict type-checking options. */
9
+ "skipLibCheck": true, /* Skip type checking all .d.ts files. */
10
+ },
11
+ "exclude": ["node_modules", "dist", "custom"], /* Exclude files from compilation. */
12
+ }
13
+
package/types.ts ADDED
@@ -0,0 +1,3 @@
1
+ export interface PluginOptions {
2
+ columns: string[];
3
+ }