diff --git a/packages/oer-finder-api-client/.gitignore b/packages/oer-finder-api-client/.gitignore index e6367a1..fe0a2ec 100644 --- a/packages/oer-finder-api-client/.gitignore +++ b/packages/oer-finder-api-client/.gitignore @@ -1,3 +1,3 @@ node_modules .env -dist +!dist \ No newline at end of file diff --git a/packages/oer-finder-api-client/dist/LICENSES.txt b/packages/oer-finder-api-client/dist/LICENSES.txt new file mode 100644 index 0000000..8480365 --- /dev/null +++ b/packages/oer-finder-api-client/dist/LICENSES.txt @@ -0,0 +1 @@ +No third parties dependencies \ No newline at end of file diff --git a/packages/oer-finder-api-client/dist/generated/schema.d.ts b/packages/oer-finder-api-client/dist/generated/schema.d.ts new file mode 100644 index 0000000..8a68da7 --- /dev/null +++ b/packages/oer-finder-api-client/dist/generated/schema.d.ts @@ -0,0 +1,636 @@ +/** + * This file was auto-generated by openapi-typescript. + * Do not make direct changes to the file. + */ +export interface paths { + "/health": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Health check endpoint + * @description Returns "ok" if the service is running + */ + get: operations["AppController_getHealth"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/v1/oer": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Query Open Educational Resources + * @description Search and filter OER aggregated from Nostr relays. Supports pagination and various filters including type, searchTerm, license, educational level, and language. Rate limited to 10 requests per 60 seconds per IP. + */ + get: operations["OerController_getOer"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; +} +export type webhooks = Record; +export interface components { + schemas: { + AmbMetadataSchema: { + /** + * @description JSON-LD context URI(s) + * @example [ + * "https://w3id.org/kim/amb/context.jsonld" + * ] + */ + "@context"?: Record; + /** + * @description Unique identifier (URI) of the resource + * @example https://example.org/resource/123 + */ + id?: string; + /** + * @description Type of the educational resource (e.g., LearningResource, CreativeWork) + * @example LearningResource + */ + type?: Record; + /** + * @description Name/title of the educational resource + * @example Introduction to Biology + */ + name?: string; + /** + * @description Textual description of the resource content + * @example A comprehensive guide to basic biology concepts for students + */ + description?: string; + /** + * @description Subject matter or topics covered (references to controlled vocabularies) + * @example [ + * { + * "id": "http://w3id.org/kim/hochschulfaechersystematik/n079" + * } + * ] + */ + about?: Record; + /** + * @description Keywords/tags describing the resource + * @example [ + * "biology", + * "science", + * "education" + * ] + */ + keywords?: string[]; + /** + * @description Language code(s) following BCP47 standard + * @example [ + * "en", + * "de" + * ] + */ + inLanguage?: string[]; + /** + * @description URL of a thumbnail or preview image + * @example https://example.org/images/resource-thumbnail.jpg + */ + image?: string; + /** + * @description Video or audio preview with contentUrl or embedUrl + * @example { + * "type": "VideoObject", + * "contentUrl": "https://example.org/videos/preview.mp4" + * } + */ + trailer?: Record; + /** + * @description Creator(s) of the resource (Person or Organization with name, type, and optional identifiers) + * @example [ + * { + * "type": "Person", + * "name": "Jane Doe" + * } + * ] + */ + creator?: Record; + /** + * @description Additional contributor(s) to the resource + * @example [ + * { + * "type": "Person", + * "name": "John Smith" + * } + * ] + */ + contributor?: Record; + /** + * @description Organizational affiliation of the creator + * @example { + * "type": "Organization", + * "name": "University of Example" + * } + */ + affiliation?: Record; + /** + * @description Date the resource was created (ISO 8601 format) + * @example 2024-01-15 + */ + dateCreated?: string; + /** + * @description Date the resource was published (ISO 8601 format) + * @example 2024-02-01 + */ + datePublished?: string; + /** + * @description Date the resource was last modified (ISO 8601 format) + * @example 2024-03-10 + */ + dateModified?: string; + /** + * @description Publisher(s) of the resource + * @example [ + * { + * "type": "Organization", + * "name": "Educational Press" + * } + * ] + */ + publisher?: Record; + /** + * @description Funding source(s) or program(s) + * @example [ + * { + * "type": "Organization", + * "name": "Research Foundation" + * } + * ] + */ + funder?: Record; + /** + * @description Whether the resource is free to access + * @example true + */ + isAccessibleForFree?: boolean; + /** + * @description License information (Creative Commons or other open license) + * @example { + * "id": "https://creativecommons.org/licenses/by/4.0/" + * } + */ + license?: Record; + /** + * @description Access requirements or restrictions + * @example { + * "type": "ConditionsOfAccess", + * "name": "Registration required" + * } + */ + conditionsOfAccess?: Record; + /** + * @description Type of learning resource (references to HCRT/OEHRT vocabularies) + * @example [ + * { + * "id": "https://w3id.org/kim/hcrt/worksheet" + * } + * ] + */ + learningResourceType?: Record; + /** + * @description Target audience role(s) per LRMI + * @example [ + * { + * "id": "http://purl.org/dcx/lrmi-vocabs/educationalAudienceRole/student" + * } + * ] + */ + audience?: Record; + /** + * @description Competencies that learners can achieve + * @example [ + * { + * "type": "DefinedTerm", + * "name": "Understanding cell division" + * } + * ] + */ + teaches?: Record; + /** + * @description Competencies that can be assessed/evaluated + * @example [ + * { + * "type": "DefinedTerm", + * "name": "Knowledge of photosynthesis" + * } + * ] + */ + assesses?: Record; + /** + * @description Prerequisites for understanding the resource + * @example [ + * { + * "type": "DefinedTerm", + * "name": "Basic chemistry knowledge" + * } + * ] + */ + competencyRequired?: Record; + /** + * @description Educational level or stage (references to educational level vocabularies) + * @example [ + * { + * "id": "https://w3id.org/kim/educationalLevel/level_06" + * } + * ] + */ + educationalLevel?: Record; + /** + * @description Learning method (expositive/active/mixed) + * @example { + * "id": "http://w3id.org/kim/interactivitytype/mixed" + * } + */ + interactivityType?: Record; + /** + * @description Source resource for derivative works + * @example [ + * { + * "id": "https://example.org/original-resource" + * } + * ] + */ + isBasedOn?: Record; + /** + * @description Parent resource(s) or collection(s) + * @example [ + * { + * "id": "https://example.org/course/biology-101" + * } + * ] + */ + isPartOf?: Record; + /** + * @description Child or component resource(s) + * @example [ + * { + * "id": "https://example.org/lesson/cell-structure" + * } + * ] + */ + hasPart?: Record; + /** + * @description Metadata provider and creation information + * @example [ + * { + * "type": "WebPage", + * "dateCreated": "2024-01-15", + * "provider": { + * "type": "Organization", + * "name": "Metadata Service" + * } + * } + * ] + */ + mainEntityOfPage?: Record; + /** + * @description Playback duration (ISO 8601 format) + * @example PT1H30M + */ + duration?: string; + /** + * @description Download options with MediaObject details + * @example [ + * { + * "type": "MediaObject", + * "contentUrl": "https://example.org/downloads/resource.pdf", + * "encodingFormat": "application/pdf" + * } + * ] + */ + encoding?: Record; + /** + * @description Subtitle files for audiovisual content + * @example [ + * { + * "type": "MediaObject", + * "contentUrl": "https://example.org/captions/en.vtt", + * "inLanguage": "en" + * } + * ] + */ + caption?: Record; + }; + ImageUrlsSchema: { + /** + * @description High resolution image URL (original size with optimization) + * @example http://localhost:8080/rs:fit:0:0/plain/https%3A%2F%2Fexample.org%2Fimage.jpg + */ + high: string; + /** + * @description Medium thumbnail URL (approximately 400px width) + * @example http://localhost:8080/rs:fit:400:0/plain/https%3A%2F%2Fexample.org%2Fimage.jpg + */ + medium: string; + /** + * @description Small thumbnail URL (approximately 200px width) + * @example http://localhost:8080/rs:fit:200:0/plain/https%3A%2F%2Fexample.org%2Fimage.jpg + */ + small: string; + }; + CreatorSchema: { + /** + * @description Type of creator (e.g., "person", "organization") + * @example person + */ + type: string; + /** + * @description Name of the creator + * @example Jane Doe + */ + name: string; + /** + * @description URL to the creator profile or resource, or null if unavailable + * @example https://example.org/creator/jane-doe + */ + link: string | null; + }; + OerItemSchema: { + /** + * @description Unique identifier (UUID) + * @example 550e8400-e29b-41d4-a716-446655440000 + */ + id: string; + /** + * @description URL of the resource + * @example https://w3id.org/kim/hcrt/worksheet + */ + url: Record | null; + /** + * @description License URI + * @example https://creativecommons.org/licenses/by/4.0/ + */ + license_uri: Record | null; + /** + * @description Whether the resource is free to use + * @example true + */ + free_to_use: Record | null; + /** + * @description MIME type of the file + * @example image/jpeg + */ + file_mime_type: Record | null; + /** + * @description AMB metadata object containing type, name, educational level, language, etc. Note: Additional fields beyond the schema definition may be present. + * @example { + * "type": "LearningResource", + * "name": "Introduction to TypeScript", + * "educationalLevel": "Beginner", + * "inLanguage": [ + * "en" + * ], + * "learningResourceType": "Tutorial" + * } + */ + amb_metadata: components["schemas"]["AmbMetadataSchema"] | null; + /** + * @description Array of keywords associated with the resource + * @example [ + * "typescript", + * "programming", + * "tutorial" + * ] + */ + keywords: string[] | null; + /** + * @description Dimensions of the file (e.g., for images or videos) + * @example 1920x1080 + */ + file_dim: Record | null; + /** + * @description Size of the file in bytes + * @example 1024000 + */ + file_size: Record | null; + /** + * @description Alternative text for the file + * @example A diagram showing TypeScript type system + */ + file_alt: Record | null; + /** + * @description Name/title of the resource + * @example Introduction to TypeScript + */ + name: string | null; + /** + * @description Description of the resource + * @example A comprehensive guide to learning TypeScript for beginners + */ + description: string | null; + /** + * @description Attribution/copyright notice for the resource (e.g., for external sources) + * @example Pictographic symbols are the property of the Government of Aragón + */ + attribution: string | null; + /** + * @description Audience URI + * @example http://purl.org/dcx/lrmi-vocabs/educationalAudienceRole/student + */ + audience_uri: Record | null; + /** + * @description Educational level URI + * @example https://w3id.org/kim/educationalLevel/level_06 + */ + educational_level_uri: Record | null; + /** + * @description Data source identifier (e.g., "nostr" for Nostr database, "arasaac" for ARASAAC adapter) + * @example nostr + */ + source: string; + /** + * @description Nostr event ID for the AMB event + * @example abc123def456 + */ + event_amb_id: Record | null; + /** + * @description Nostr event ID for the file event + * @example xyz789uvw012 + */ + event_file_id: Record | null; + /** + * Format: date-time + * @description Timestamp when the record was created in the database + * @example 2024-01-01T00:00:00Z + */ + created_at: string; + /** + * Format: date-time + * @description Timestamp when the record was last updated in the database + * @example 2024-01-15T10:30:00Z + */ + updated_at: string; + /** + * @description Image proxy URLs for optimized image loading. Contains high, medium, and small thumbnail variants. Null when imgproxy is not configured or no image URL is available. + * @example { + * "high": "http://localhost:8080/rs:fit:0:0/plain/https%3A%2F%2Fexample.org%2Fimage.jpg", + * "medium": "http://localhost:8080/rs:fit:400:0/plain/https%3A%2F%2Fexample.org%2Fimage.jpg", + * "small": "http://localhost:8080/rs:fit:200:0/plain/https%3A%2F%2Fexample.org%2Fimage.jpg" + * } + */ + images: components["schemas"]["ImageUrlsSchema"] | null; + /** + * @description List of creators (persons or organizations) + * @example [ + * { + * "type": "person", + * "name": "Jane Doe", + * "link": null + * } + * ] + */ + creators: components["schemas"]["CreatorSchema"][]; + }; + OerMetadataSchema: { + /** + * @description Total number of resources matching the query + * @example 150 + */ + total: number; + /** + * @description Current page number + * @example 1 + */ + page: number; + /** + * @description Number of items per page + * @example 20 + */ + pageSize: number; + /** + * @description Total number of pages + * @example 8 + */ + totalPages: number; + }; + OerListResponseSchema: { + /** @description Array of Open Educational Resources */ + data: components["schemas"]["OerItemSchema"][]; + /** @description Pagination metadata */ + meta: components["schemas"]["OerMetadataSchema"]; + }; + }; + responses: never; + parameters: never; + requestBodies: never; + headers: never; + pathItems: never; +} +export type $defs = Record; +export interface operations { + AppController_getHealth: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Service is healthy */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": string; + }; + }; + }; + }; + OerController_getOer: { + parameters: { + query?: { + /** @description Page number (min: 1, default: 1) */ + page?: number; + /** @description Items per page (min: 1, max: 20, default: 20) */ + pageSize?: number; + /** @description Data source to query. Default (or "nostr"): Nostr database only. Use adapter ID (e.g., "arasaac") to query external sources. */ + source?: string; + /** @description Filter by MIME type or AMB metadata type (partial match) */ + type?: string; + /** @description Search term (searches in name, description, and keywords array) */ + searchTerm?: string; + /** @description Filter by license URI (exact match) */ + license?: string; + /** @description Filter by free for use status (true or false) */ + free_for_use?: boolean; + /** @description Filter by educational level URI (exact match) */ + educational_level?: string; + /** @description Filter by language code (2-3 lowercase letters, e.g., "en", "fr") */ + language?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successfully retrieved OER list */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["OerListResponseSchema"]; + }; + }; + /** @description Invalid query parameters */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + /** @example 400 */ + statusCode?: number; + message?: string | string[]; + /** @example Bad Request */ + error?: string; + }; + }; + }; + /** @description Rate limit exceeded (10 requests per 60 seconds per IP) */ + 429: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + /** @example 429 */ + statusCode?: number; + /** @example ThrottlerException: Too Many Requests */ + message?: string; + }; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; +} +//# sourceMappingURL=schema.d.ts.map \ No newline at end of file diff --git a/packages/oer-finder-api-client/dist/generated/schema.d.ts.map b/packages/oer-finder-api-client/dist/generated/schema.d.ts.map new file mode 100644 index 0000000..28d532f --- /dev/null +++ b/packages/oer-finder-api-client/dist/generated/schema.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../generated/schema.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/oer-finder-api-client/dist/index.cjs b/packages/oer-finder-api-client/dist/index.cjs new file mode 100644 index 0000000..ecbf1ba --- /dev/null +++ b/packages/oer-finder-api-client/dist/index.cjs @@ -0,0 +1 @@ +"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const c=require("openapi-fetch");function a(r,e){return c({baseUrl:r.replace(/\/$/,""),headers:e==null?void 0:e.headers,fetch:e==null?void 0:e.fetch})}exports.createOerClient=a; diff --git a/packages/oer-finder-api-client/dist/index.d.ts b/packages/oer-finder-api-client/dist/index.d.ts new file mode 100644 index 0000000..d47910c --- /dev/null +++ b/packages/oer-finder-api-client/dist/index.d.ts @@ -0,0 +1,63 @@ +/** + * @edufeed-org/api-client + * Auto-generated API client for the OER Aggregator + * + * This package provides a type-safe client for interacting with the OER Aggregator API. + * The client is automatically generated from the OpenAPI specification using openapi-typescript. + * + * Usage: + * ```typescript + * import { createOerClient } from '@edufeed-org/api-client'; + * + * const client = createOerClient('https://api.example.com'); + * const { data, error } = await client.GET('/api/v1/oer', { + * params: { query: { page: 1, pageSize: 10 } } + * }); + * ``` + */ +import createClient from 'openapi-fetch'; +import type { paths, components, operations } from '../generated/schema.js'; +export type OerClient = ReturnType>; +/** + * Create a new OER API client + * + * @param baseUrl - Base URL of the API (e.g., 'https://api.example.com') + * @param options - Additional client options (headers, etc.) + * @returns Type-safe OER API client instance + * + * @example + * ```typescript + * const client = createOerClient('https://api.example.com'); + * + * // List OER resources + * const { data, error } = await client.GET('/api/v1/oer', { + * params: { + * query: { + * page: 1, + * pageSize: 10, + * type: 'image', + * } + * } + * }); + * + * if (error) { + * console.error('Error:', error); + * } else { + * console.log('Results:', data); + * } + * + * // Health check + * const { data: health } = await client.GET('/health'); + * ``` + */ +export declare function createOerClient(baseUrl: string, options?: { + headers?: HeadersInit; + fetch?: typeof fetch; +}): OerClient; +export type { paths, components, operations } from '../generated/schema.js'; +export type OerItem = components['schemas']['OerItemSchema']; +export type OerMetadata = components['schemas']['OerMetadataSchema']; +export type OerListResponse = components['schemas']['OerListResponseSchema']; +export type ImageUrls = components['schemas']['ImageUrlsSchema']; +export type OerQueryParams = operations['OerController_getOer']['parameters']['query']; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/packages/oer-finder-api-client/dist/index.d.ts.map b/packages/oer-finder-api-client/dist/index.d.ts.map new file mode 100644 index 0000000..20da223 --- /dev/null +++ b/packages/oer-finder-api-client/dist/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,YAAY,MAAM,eAAe,CAAC;AACzC,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAE5E,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;AAE/D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;IACR,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACtB,GACA,SAAS,CAMX;AAGD,YAAY,EAAE,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAG5E,MAAM,MAAM,OAAO,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,eAAe,CAAC,CAAC;AAC7D,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,mBAAmB,CAAC,CAAC;AACrE,MAAM,MAAM,eAAe,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,uBAAuB,CAAC,CAAC;AAC7E,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,iBAAiB,CAAC,CAAC;AAGjE,MAAM,MAAM,cAAc,GAAG,UAAU,CAAC,sBAAsB,CAAC,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,CAAC"} \ No newline at end of file diff --git a/packages/oer-finder-api-client/dist/index.js b/packages/oer-finder-api-client/dist/index.js new file mode 100644 index 0000000..a07dc28 --- /dev/null +++ b/packages/oer-finder-api-client/dist/index.js @@ -0,0 +1,12 @@ +import a from "openapi-fetch"; +function f(r, e) { + return a({ + baseUrl: r.replace(/\/$/, ""), + // Remove trailing slash + headers: e == null ? void 0 : e.headers, + fetch: e == null ? void 0 : e.fetch + }); +} +export { + f as createOerClient +}; diff --git a/packages/oer-finder-api-client/dist/src/index.d.ts b/packages/oer-finder-api-client/dist/src/index.d.ts new file mode 100644 index 0000000..d47910c --- /dev/null +++ b/packages/oer-finder-api-client/dist/src/index.d.ts @@ -0,0 +1,63 @@ +/** + * @edufeed-org/api-client + * Auto-generated API client for the OER Aggregator + * + * This package provides a type-safe client for interacting with the OER Aggregator API. + * The client is automatically generated from the OpenAPI specification using openapi-typescript. + * + * Usage: + * ```typescript + * import { createOerClient } from '@edufeed-org/api-client'; + * + * const client = createOerClient('https://api.example.com'); + * const { data, error } = await client.GET('/api/v1/oer', { + * params: { query: { page: 1, pageSize: 10 } } + * }); + * ``` + */ +import createClient from 'openapi-fetch'; +import type { paths, components, operations } from '../generated/schema.js'; +export type OerClient = ReturnType>; +/** + * Create a new OER API client + * + * @param baseUrl - Base URL of the API (e.g., 'https://api.example.com') + * @param options - Additional client options (headers, etc.) + * @returns Type-safe OER API client instance + * + * @example + * ```typescript + * const client = createOerClient('https://api.example.com'); + * + * // List OER resources + * const { data, error } = await client.GET('/api/v1/oer', { + * params: { + * query: { + * page: 1, + * pageSize: 10, + * type: 'image', + * } + * } + * }); + * + * if (error) { + * console.error('Error:', error); + * } else { + * console.log('Results:', data); + * } + * + * // Health check + * const { data: health } = await client.GET('/health'); + * ``` + */ +export declare function createOerClient(baseUrl: string, options?: { + headers?: HeadersInit; + fetch?: typeof fetch; +}): OerClient; +export type { paths, components, operations } from '../generated/schema.js'; +export type OerItem = components['schemas']['OerItemSchema']; +export type OerMetadata = components['schemas']['OerMetadataSchema']; +export type OerListResponse = components['schemas']['OerListResponseSchema']; +export type ImageUrls = components['schemas']['ImageUrlsSchema']; +export type OerQueryParams = operations['OerController_getOer']['parameters']['query']; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/packages/oer-finder-api-client/dist/src/index.d.ts.map b/packages/oer-finder-api-client/dist/src/index.d.ts.map new file mode 100644 index 0000000..20da223 --- /dev/null +++ b/packages/oer-finder-api-client/dist/src/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,YAAY,MAAM,eAAe,CAAC;AACzC,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAE5E,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;AAE/D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;IACR,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACtB,GACA,SAAS,CAMX;AAGD,YAAY,EAAE,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAG5E,MAAM,MAAM,OAAO,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,eAAe,CAAC,CAAC;AAC7D,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,mBAAmB,CAAC,CAAC;AACrE,MAAM,MAAM,eAAe,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,uBAAuB,CAAC,CAAC;AAC7E,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,iBAAiB,CAAC,CAAC;AAGjE,MAAM,MAAM,cAAc,GAAG,UAAU,CAAC,sBAAsB,CAAC,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,CAAC"} \ No newline at end of file diff --git a/packages/oer-finder-plugin/.gitignore b/packages/oer-finder-plugin/.gitignore index e6367a1..fe0a2ec 100644 --- a/packages/oer-finder-plugin/.gitignore +++ b/packages/oer-finder-plugin/.gitignore @@ -1,3 +1,3 @@ node_modules .env -dist +!dist \ No newline at end of file diff --git a/packages/oer-finder-plugin/dist/LICENSES.txt b/packages/oer-finder-plugin/dist/LICENSES.txt new file mode 100644 index 0000000..165da4b --- /dev/null +++ b/packages/oer-finder-plugin/dist/LICENSES.txt @@ -0,0 +1,168 @@ +Name: @lit/reactive-element +Version: 2.1.1 +License: BSD-3-Clause +Private: false +Description: A simple low level base class for creating fast, lightweight web components +Repository: git+https://github.com/lit/lit.git +Homepage: https://lit.dev/ +Author: Google LLC +License Copyright: +=== + +BSD 3-Clause License + +Copyright (c) 2017 Google LLC. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +--- + +Name: lit-html +Version: 3.3.1 +License: BSD-3-Clause +Private: false +Description: HTML templates literals in JavaScript +Repository: git+https://github.com/lit/lit.git +Homepage: https://lit.dev/ +Author: Google LLC +License Copyright: +=== + +BSD 3-Clause License + +Copyright (c) 2017 Google LLC. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +--- + +Name: lit-element +Version: 4.2.1 +License: BSD-3-Clause +Private: false +Description: A simple base class for creating fast, lightweight web components +Repository: git+https://github.com/lit/lit.git +Homepage: https://lit.dev/ +Author: Google LLC +License Copyright: +=== + +BSD 3-Clause License + +Copyright (c) 2017 Google LLC. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +--- + +Name: openapi-fetch +Version: 0.13.8 +License: MIT +Private: false +Description: Fast, type-safe fetch client for your OpenAPI schema. Only 6 kb (min). Works with React, Vue, Svelte, or vanilla JS. +Repository: https://github.com/openapi-ts/openapi-typescript +Homepage: https://openapi-ts.dev +Author: Drew Powers +License Copyright: +=== + +MIT License + +Copyright (c) 2023 Drew Powers + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--- + +Name: @edufeed-org/oer-finder-api-client +Version: 0.0.4 +License: MIT +Private: false +Description: Auto-generated API client for OER Aggregator +Repository: https://github.com/edufeed-org/oer-finder-plugin.git +Author: B310 Digital GmbH \ No newline at end of file diff --git a/packages/oer-finder-plugin/dist/constants.d.ts b/packages/oer-finder-plugin/dist/constants.d.ts new file mode 100644 index 0000000..b87e783 --- /dev/null +++ b/packages/oer-finder-plugin/dist/constants.d.ts @@ -0,0 +1,33 @@ +/** + * Default source identifier for resources from the Nostr network. + */ +export declare const DEFAULT_SOURCE = "nostr"; +/** + * Common Creative Commons and other OER licenses + * Full URIs and human-readable short names + */ +export interface License { + uri: string; + shortName: string; +} +export declare const COMMON_LICENSES: License[]; +/** + * Get short name for a license URI + */ +export declare function getLicenseShortName(uri: string): string | null; +/** + * Language options for the filter dropdown + */ +export interface LanguageOption { + code: string; + label: string; +} +export declare const FILTER_LANGUAGES: LanguageOption[]; +/** + * Resource type options for the type filter dropdown + */ +export interface ResourceTypeOption { + value: string; + label: string; +} +export declare const RESOURCE_TYPES: ResourceTypeOption[]; diff --git a/packages/oer-finder-plugin/dist/index.d.ts b/packages/oer-finder-plugin/dist/index.d.ts new file mode 100644 index 0000000..c5b42e8 --- /dev/null +++ b/packages/oer-finder-plugin/dist/index.d.ts @@ -0,0 +1,48 @@ +/** + * @edufeed-org/frontend-plugin + * Web Components plugin for the OER Aggregator + * + * This package provides framework-agnostic Web Components for displaying + * and interacting with Open Educational Resources. + * + * Usage: + * ```html + * + * + * + * ``` + * + * Customize colors via CSS variables: + * ```css + * oer-search, oer-list { + * --primary-color: #667eea; + * --primary-hover-color: #5568d3; + * --secondary-color: #764ba2; + * --background-card: #ffffff; + * --background-form: #f8f9fa; + * --background-input: #ffffff; + * --text-primary: #2d3748; + * --text-secondary: #4a5568; + * --text-muted: #718096; + * } + * ``` + * + * Or via npm: + * ```typescript + * import '@edufeed-org/frontend-plugin'; + * ``` + */ +import './oer-card/OerCard.js'; +import './oer-list/OerList.js'; +import './oer-search/OerSearch.js'; +import './pagination/Pagination.js'; +export { OerCardElement, type OerCardClickEvent } from './oer-card/OerCard.js'; +export { OerListElement } from './oer-list/OerList.js'; +export { OerSearchElement, type OerSearchResultEvent, type SearchParams, type SourceOption, } from './oer-search/OerSearch.js'; +export { PaginationElement, type OerPageChangeEvent } from './pagination/Pagination.js'; +export type { SupportedLanguage, OerCardTranslations, OerListTranslations, OerSearchTranslations, PaginationTranslations, Translations, } from './translations.js'; +export { getTranslations, getCardTranslations, getListTranslations, getSearchTranslations, getPaginationTranslations, } from './translations.js'; +export { truncateText, truncateTitle, truncateContent, truncateLabel, shortenLabels, } from './utils.js'; +export type { OerItem, OerMetadata, OerListResponse, OerQueryParams, OerClient, ImageUrls, } from '@edufeed-org/oer-finder-api-client'; +export { createOerClient } from '@edufeed-org/oer-finder-api-client'; +export declare const VERSION = "0.0.1"; diff --git a/packages/oer-finder-plugin/dist/oer-card/OerCard.d.ts b/packages/oer-finder-plugin/dist/oer-card/OerCard.d.ts new file mode 100644 index 0000000..236eb79 --- /dev/null +++ b/packages/oer-finder-plugin/dist/oer-card/OerCard.d.ts @@ -0,0 +1,22 @@ +import { LitElement } from 'lit'; +import type { components } from '@edufeed-org/oer-finder-api-client'; +import { type SupportedLanguage } from '../translations.js'; +type OerItem = components['schemas']['OerItemSchema']; +export interface OerCardClickEvent { + oer: OerItem; +} +export declare class OerCardElement extends LitElement { + static styles: import("lit").CSSResult; + oer: OerItem | null; + language: SupportedLanguage; + private get t(); + private handleImageClick; + private getLicenseName; + render(): import("lit").TemplateResult<1>; +} +declare global { + interface HTMLElementTagNameMap { + 'oer-card': OerCardElement; + } +} +export {}; diff --git a/packages/oer-finder-plugin/dist/oer-card/OerCard.test.d.ts b/packages/oer-finder-plugin/dist/oer-card/OerCard.test.d.ts new file mode 100644 index 0000000..d64a441 --- /dev/null +++ b/packages/oer-finder-plugin/dist/oer-card/OerCard.test.d.ts @@ -0,0 +1 @@ +import './OerCard.js'; diff --git a/packages/oer-finder-plugin/dist/oer-card/styles.d.ts b/packages/oer-finder-plugin/dist/oer-card/styles.d.ts new file mode 100644 index 0000000..1c75ade --- /dev/null +++ b/packages/oer-finder-plugin/dist/oer-card/styles.d.ts @@ -0,0 +1 @@ +export declare const styles: import("lit").CSSResult; diff --git a/packages/oer-finder-plugin/dist/oer-list/OerList.d.ts b/packages/oer-finder-plugin/dist/oer-list/OerList.d.ts new file mode 100644 index 0000000..f822756 --- /dev/null +++ b/packages/oer-finder-plugin/dist/oer-list/OerList.d.ts @@ -0,0 +1,20 @@ +import { LitElement } from 'lit'; +import type { components } from '@edufeed-org/oer-finder-api-client'; +import '../oer-card/OerCard.js'; +import { type SupportedLanguage } from '../translations.js'; +type OerItem = components['schemas']['OerItemSchema']; +export declare class OerListElement extends LitElement { + static styles: import("lit").CSSResult; + oers: OerItem[]; + loading: boolean; + error: string | null; + language: SupportedLanguage; + private get t(); + render(): import("lit").TemplateResult<1>; +} +declare global { + interface HTMLElementTagNameMap { + 'oer-list': OerListElement; + } +} +export {}; diff --git a/packages/oer-finder-plugin/dist/oer-list/OerList.test.d.ts b/packages/oer-finder-plugin/dist/oer-list/OerList.test.d.ts new file mode 100644 index 0000000..c56b889 --- /dev/null +++ b/packages/oer-finder-plugin/dist/oer-list/OerList.test.d.ts @@ -0,0 +1 @@ +import './OerList.js'; diff --git a/packages/oer-finder-plugin/dist/oer-list/styles.d.ts b/packages/oer-finder-plugin/dist/oer-list/styles.d.ts new file mode 100644 index 0000000..1c75ade --- /dev/null +++ b/packages/oer-finder-plugin/dist/oer-list/styles.d.ts @@ -0,0 +1 @@ +export declare const styles: import("lit").CSSResult; diff --git a/packages/oer-finder-plugin/dist/oer-plugin.js b/packages/oer-finder-plugin/dist/oer-plugin.js new file mode 100644 index 0000000..1caf6a5 --- /dev/null +++ b/packages/oer-finder-plugin/dist/oer-plugin.js @@ -0,0 +1,2404 @@ +/** + * @license + * Copyright 2019 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +const ee = globalThis, xe = ee.ShadowRoot && (ee.ShadyCSS === void 0 || ee.ShadyCSS.nativeShadow) && "adoptedStyleSheets" in Document.prototype && "replace" in CSSStyleSheet.prototype, ve = Symbol(), Ce = /* @__PURE__ */ new WeakMap(); +let We = class { + constructor(e, t, i) { + if (this._$cssResult$ = !0, i !== ve) throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead."); + this.cssText = e, this.t = t; + } + get styleSheet() { + let e = this.o; + const t = this.t; + if (xe && e === void 0) { + const i = t !== void 0 && t.length === 1; + i && (e = Ce.get(t)), e === void 0 && ((this.o = e = new CSSStyleSheet()).replaceSync(this.cssText), i && Ce.set(t, e)); + } + return e; + } + toString() { + return this.cssText; + } +}; +const tt = (r) => new We(typeof r == "string" ? r : r + "", void 0, ve), se = (r, ...e) => { + const t = r.length === 1 ? r[0] : e.reduce(((i, s, n) => i + ((o) => { + if (o._$cssResult$ === !0) return o.cssText; + if (typeof o == "number") return o; + throw Error("Value passed to 'css' function must be a 'css' function result: " + o + ". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security."); + })(s) + r[n + 1]), r[0]); + return new We(t, r, ve); +}, rt = (r, e) => { + if (xe) r.adoptedStyleSheets = e.map(((t) => t instanceof CSSStyleSheet ? t : t.styleSheet)); + else for (const t of e) { + const i = document.createElement("style"), s = ee.litNonce; + s !== void 0 && i.setAttribute("nonce", s), i.textContent = t.cssText, r.appendChild(i); + } +}, ke = xe ? (r) => r : (r) => r instanceof CSSStyleSheet ? ((e) => { + let t = ""; + for (const i of e.cssRules) t += i.cssText; + return tt(t); +})(r) : r; +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +const { is: st, defineProperty: it, getOwnPropertyDescriptor: nt, getOwnPropertyNames: ot, getOwnPropertySymbols: at, getPrototypeOf: lt } = Object, A = globalThis, Oe = A.trustedTypes, ct = Oe ? Oe.emptyScript : "", fe = A.reactiveElementPolyfillSupport, H = (r, e) => r, te = { toAttribute(r, e) { + switch (e) { + case Boolean: + r = r ? ct : null; + break; + case Object: + case Array: + r = r == null ? r : JSON.stringify(r); + } + return r; +}, fromAttribute(r, e) { + let t = r; + switch (e) { + case Boolean: + t = r !== null; + break; + case Number: + t = r === null ? null : Number(r); + break; + case Object: + case Array: + try { + t = JSON.parse(r); + } catch { + t = null; + } + } + return t; +} }, $e = (r, e) => !st(r, e), ze = { attribute: !0, type: String, converter: te, reflect: !1, useDefault: !1, hasChanged: $e }; +Symbol.metadata ?? (Symbol.metadata = Symbol("metadata")), A.litPropertyMetadata ?? (A.litPropertyMetadata = /* @__PURE__ */ new WeakMap()); +let U = class extends HTMLElement { + static addInitializer(e) { + this._$Ei(), (this.l ?? (this.l = [])).push(e); + } + static get observedAttributes() { + return this.finalize(), this._$Eh && [...this._$Eh.keys()]; + } + static createProperty(e, t = ze) { + if (t.state && (t.attribute = !1), this._$Ei(), this.prototype.hasOwnProperty(e) && ((t = Object.create(t)).wrapped = !0), this.elementProperties.set(e, t), !t.noAccessor) { + const i = Symbol(), s = this.getPropertyDescriptor(e, i, t); + s !== void 0 && it(this.prototype, e, s); + } + } + static getPropertyDescriptor(e, t, i) { + const { get: s, set: n } = nt(this.prototype, e) ?? { get() { + return this[t]; + }, set(o) { + this[t] = o; + } }; + return { get: s, set(o) { + const a = s == null ? void 0 : s.call(this); + n == null || n.call(this, o), this.requestUpdate(e, a, i); + }, configurable: !0, enumerable: !0 }; + } + static getPropertyOptions(e) { + return this.elementProperties.get(e) ?? ze; + } + static _$Ei() { + if (this.hasOwnProperty(H("elementProperties"))) return; + const e = lt(this); + e.finalize(), e.l !== void 0 && (this.l = [...e.l]), this.elementProperties = new Map(e.elementProperties); + } + static finalize() { + if (this.hasOwnProperty(H("finalized"))) return; + if (this.finalized = !0, this._$Ei(), this.hasOwnProperty(H("properties"))) { + const t = this.properties, i = [...ot(t), ...at(t)]; + for (const s of i) this.createProperty(s, t[s]); + } + const e = this[Symbol.metadata]; + if (e !== null) { + const t = litPropertyMetadata.get(e); + if (t !== void 0) for (const [i, s] of t) this.elementProperties.set(i, s); + } + this._$Eh = /* @__PURE__ */ new Map(); + for (const [t, i] of this.elementProperties) { + const s = this._$Eu(t, i); + s !== void 0 && this._$Eh.set(s, t); + } + this.elementStyles = this.finalizeStyles(this.styles); + } + static finalizeStyles(e) { + const t = []; + if (Array.isArray(e)) { + const i = new Set(e.flat(1 / 0).reverse()); + for (const s of i) t.unshift(ke(s)); + } else e !== void 0 && t.push(ke(e)); + return t; + } + static _$Eu(e, t) { + const i = t.attribute; + return i === !1 ? void 0 : typeof i == "string" ? i : typeof e == "string" ? e.toLowerCase() : void 0; + } + constructor() { + super(), this._$Ep = void 0, this.isUpdatePending = !1, this.hasUpdated = !1, this._$Em = null, this._$Ev(); + } + _$Ev() { + var e; + this._$ES = new Promise(((t) => this.enableUpdating = t)), this._$AL = /* @__PURE__ */ new Map(), this._$E_(), this.requestUpdate(), (e = this.constructor.l) == null || e.forEach(((t) => t(this))); + } + addController(e) { + var t; + (this._$EO ?? (this._$EO = /* @__PURE__ */ new Set())).add(e), this.renderRoot !== void 0 && this.isConnected && ((t = e.hostConnected) == null || t.call(e)); + } + removeController(e) { + var t; + (t = this._$EO) == null || t.delete(e); + } + _$E_() { + const e = /* @__PURE__ */ new Map(), t = this.constructor.elementProperties; + for (const i of t.keys()) this.hasOwnProperty(i) && (e.set(i, this[i]), delete this[i]); + e.size > 0 && (this._$Ep = e); + } + createRenderRoot() { + const e = this.shadowRoot ?? this.attachShadow(this.constructor.shadowRootOptions); + return rt(e, this.constructor.elementStyles), e; + } + connectedCallback() { + var e; + this.renderRoot ?? (this.renderRoot = this.createRenderRoot()), this.enableUpdating(!0), (e = this._$EO) == null || e.forEach(((t) => { + var i; + return (i = t.hostConnected) == null ? void 0 : i.call(t); + })); + } + enableUpdating(e) { + } + disconnectedCallback() { + var e; + (e = this._$EO) == null || e.forEach(((t) => { + var i; + return (i = t.hostDisconnected) == null ? void 0 : i.call(t); + })); + } + attributeChangedCallback(e, t, i) { + this._$AK(e, i); + } + _$ET(e, t) { + var n; + const i = this.constructor.elementProperties.get(e), s = this.constructor._$Eu(e, i); + if (s !== void 0 && i.reflect === !0) { + const o = (((n = i.converter) == null ? void 0 : n.toAttribute) !== void 0 ? i.converter : te).toAttribute(t, i.type); + this._$Em = e, o == null ? this.removeAttribute(s) : this.setAttribute(s, o), this._$Em = null; + } + } + _$AK(e, t) { + var n, o; + const i = this.constructor, s = i._$Eh.get(e); + if (s !== void 0 && this._$Em !== s) { + const a = i.getPropertyOptions(s), c = typeof a.converter == "function" ? { fromAttribute: a.converter } : ((n = a.converter) == null ? void 0 : n.fromAttribute) !== void 0 ? a.converter : te; + this._$Em = s; + const h = c.fromAttribute(t, a.type); + this[s] = h ?? ((o = this._$Ej) == null ? void 0 : o.get(s)) ?? h, this._$Em = null; + } + } + requestUpdate(e, t, i) { + var s; + if (e !== void 0) { + const n = this.constructor, o = this[e]; + if (i ?? (i = n.getPropertyOptions(e)), !((i.hasChanged ?? $e)(o, t) || i.useDefault && i.reflect && o === ((s = this._$Ej) == null ? void 0 : s.get(e)) && !this.hasAttribute(n._$Eu(e, i)))) return; + this.C(e, t, i); + } + this.isUpdatePending === !1 && (this._$ES = this._$EP()); + } + C(e, t, { useDefault: i, reflect: s, wrapped: n }, o) { + i && !(this._$Ej ?? (this._$Ej = /* @__PURE__ */ new Map())).has(e) && (this._$Ej.set(e, o ?? t ?? this[e]), n !== !0 || o !== void 0) || (this._$AL.has(e) || (this.hasUpdated || i || (t = void 0), this._$AL.set(e, t)), s === !0 && this._$Em !== e && (this._$Eq ?? (this._$Eq = /* @__PURE__ */ new Set())).add(e)); + } + async _$EP() { + this.isUpdatePending = !0; + try { + await this._$ES; + } catch (t) { + Promise.reject(t); + } + const e = this.scheduleUpdate(); + return e != null && await e, !this.isUpdatePending; + } + scheduleUpdate() { + return this.performUpdate(); + } + performUpdate() { + var i; + if (!this.isUpdatePending) return; + if (!this.hasUpdated) { + if (this.renderRoot ?? (this.renderRoot = this.createRenderRoot()), this._$Ep) { + for (const [n, o] of this._$Ep) this[n] = o; + this._$Ep = void 0; + } + const s = this.constructor.elementProperties; + if (s.size > 0) for (const [n, o] of s) { + const { wrapped: a } = o, c = this[n]; + a !== !0 || this._$AL.has(n) || c === void 0 || this.C(n, void 0, o, c); + } + } + let e = !1; + const t = this._$AL; + try { + e = this.shouldUpdate(t), e ? (this.willUpdate(t), (i = this._$EO) == null || i.forEach(((s) => { + var n; + return (n = s.hostUpdate) == null ? void 0 : n.call(s); + })), this.update(t)) : this._$EM(); + } catch (s) { + throw e = !1, this._$EM(), s; + } + e && this._$AE(t); + } + willUpdate(e) { + } + _$AE(e) { + var t; + (t = this._$EO) == null || t.forEach(((i) => { + var s; + return (s = i.hostUpdated) == null ? void 0 : s.call(i); + })), this.hasUpdated || (this.hasUpdated = !0, this.firstUpdated(e)), this.updated(e); + } + _$EM() { + this._$AL = /* @__PURE__ */ new Map(), this.isUpdatePending = !1; + } + get updateComplete() { + return this.getUpdateComplete(); + } + getUpdateComplete() { + return this._$ES; + } + shouldUpdate(e) { + return !0; + } + update(e) { + this._$Eq && (this._$Eq = this._$Eq.forEach(((t) => this._$ET(t, this[t])))), this._$EM(); + } + updated(e) { + } + firstUpdated(e) { + } +}; +U.elementStyles = [], U.shadowRootOptions = { mode: "open" }, U[H("elementProperties")] = /* @__PURE__ */ new Map(), U[H("finalized")] = /* @__PURE__ */ new Map(), fe == null || fe({ ReactiveElement: U }), (A.reactiveElementVersions ?? (A.reactiveElementVersions = [])).push("2.1.1"); +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +const D = globalThis, re = D.trustedTypes, Re = re ? re.createPolicy("lit-html", { createHTML: (r) => r }) : void 0, Ye = "$lit$", S = `lit$${Math.random().toFixed(9).slice(2)}$`, Ve = "?" + S, dt = `<${Ve}>`, O = document, I = () => O.createComment(""), F = (r) => r === null || typeof r != "object" && typeof r != "function", we = Array.isArray, ht = (r) => we(r) || typeof (r == null ? void 0 : r[Symbol.iterator]) == "function", me = `[ +\f\r]`, B = /<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g, Ue = /-->/g, Ne = />/g, P = RegExp(`>|${me}(?:([^\\s"'>=/]+)(${me}*=${me}*(?:[^ +\f\r"'\`<>=]|("|')|))|$)`, "g"), Le = /'/g, je = /"/g, Ke = /^(?:script|style|textarea|title)$/i, pt = (r) => (e, ...t) => ({ _$litType$: r, strings: e, values: t }), u = pt(1), N = Symbol.for("lit-noChange"), m = Symbol.for("lit-nothing"), Me = /* @__PURE__ */ new WeakMap(), C = O.createTreeWalker(O, 129); +function Je(r, e) { + if (!we(r) || !r.hasOwnProperty("raw")) throw Error("invalid template strings array"); + return Re !== void 0 ? Re.createHTML(e) : e; +} +const ut = (r, e) => { + const t = r.length - 1, i = []; + let s, n = e === 2 ? "" : e === 3 ? "" : "", o = B; + for (let a = 0; a < t; a++) { + const c = r[a]; + let h, p, l = -1, d = 0; + for (; d < c.length && (o.lastIndex = d, p = o.exec(c), p !== null); ) d = o.lastIndex, o === B ? p[1] === "!--" ? o = Ue : p[1] !== void 0 ? o = Ne : p[2] !== void 0 ? (Ke.test(p[2]) && (s = RegExp("" ? (o = s ?? B, l = -1) : p[1] === void 0 ? l = -2 : (l = o.lastIndex - p[2].length, h = p[1], o = p[3] === void 0 ? P : p[3] === '"' ? je : Le) : o === je || o === Le ? o = P : o === Ue || o === Ne ? o = B : (o = P, s = void 0); + const g = o === P && r[a + 1].startsWith("/>") ? " " : ""; + n += o === B ? c + dt : l >= 0 ? (i.push(h), c.slice(0, l) + Ye + c.slice(l) + S + g) : c + S + (l === -2 ? a : g); + } + return [Je(r, n + (r[t] || "") + (e === 2 ? "" : e === 3 ? "" : "")), i]; +}; +class q { + constructor({ strings: e, _$litType$: t }, i) { + let s; + this.parts = []; + let n = 0, o = 0; + const a = e.length - 1, c = this.parts, [h, p] = ut(e, t); + if (this.el = q.createElement(h, i), C.currentNode = this.el.content, t === 2 || t === 3) { + const l = this.el.content.firstChild; + l.replaceWith(...l.childNodes); + } + for (; (s = C.nextNode()) !== null && c.length < a; ) { + if (s.nodeType === 1) { + if (s.hasAttributes()) for (const l of s.getAttributeNames()) if (l.endsWith(Ye)) { + const d = p[o++], g = s.getAttribute(l).split(S), w = /([.?@])?(.*)/.exec(d); + c.push({ type: 1, index: n, name: w[2], strings: g, ctor: w[1] === "." ? ft : w[1] === "?" ? mt : w[1] === "@" ? bt : ie }), s.removeAttribute(l); + } else l.startsWith(S) && (c.push({ type: 6, index: n }), s.removeAttribute(l)); + if (Ke.test(s.tagName)) { + const l = s.textContent.split(S), d = l.length - 1; + if (d > 0) { + s.textContent = re ? re.emptyScript : ""; + for (let g = 0; g < d; g++) s.append(l[g], I()), C.nextNode(), c.push({ type: 2, index: ++n }); + s.append(l[d], I()); + } + } + } else if (s.nodeType === 8) if (s.data === Ve) c.push({ type: 2, index: n }); + else { + let l = -1; + for (; (l = s.data.indexOf(S, l + 1)) !== -1; ) c.push({ type: 7, index: n }), l += S.length - 1; + } + n++; + } + } + static createElement(e, t) { + const i = O.createElement("template"); + return i.innerHTML = e, i; + } +} +function L(r, e, t = r, i) { + var o, a; + if (e === N) return e; + let s = i !== void 0 ? (o = t._$Co) == null ? void 0 : o[i] : t._$Cl; + const n = F(e) ? void 0 : e._$litDirective$; + return (s == null ? void 0 : s.constructor) !== n && ((a = s == null ? void 0 : s._$AO) == null || a.call(s, !1), n === void 0 ? s = void 0 : (s = new n(r), s._$AT(r, t, i)), i !== void 0 ? (t._$Co ?? (t._$Co = []))[i] = s : t._$Cl = s), s !== void 0 && (e = L(r, s._$AS(r, e.values), s, i)), e; +} +class gt { + constructor(e, t) { + this._$AV = [], this._$AN = void 0, this._$AD = e, this._$AM = t; + } + get parentNode() { + return this._$AM.parentNode; + } + get _$AU() { + return this._$AM._$AU; + } + u(e) { + const { el: { content: t }, parts: i } = this._$AD, s = ((e == null ? void 0 : e.creationScope) ?? O).importNode(t, !0); + C.currentNode = s; + let n = C.nextNode(), o = 0, a = 0, c = i[0]; + for (; c !== void 0; ) { + if (o === c.index) { + let h; + c.type === 2 ? h = new Y(n, n.nextSibling, this, e) : c.type === 1 ? h = new c.ctor(n, c.name, c.strings, this, e) : c.type === 6 && (h = new yt(n, this, e)), this._$AV.push(h), c = i[++a]; + } + o !== (c == null ? void 0 : c.index) && (n = C.nextNode(), o++); + } + return C.currentNode = O, s; + } + p(e) { + let t = 0; + for (const i of this._$AV) i !== void 0 && (i.strings !== void 0 ? (i._$AI(e, i, t), t += i.strings.length - 2) : i._$AI(e[t])), t++; + } +} +class Y { + get _$AU() { + var e; + return ((e = this._$AM) == null ? void 0 : e._$AU) ?? this._$Cv; + } + constructor(e, t, i, s) { + this.type = 2, this._$AH = m, this._$AN = void 0, this._$AA = e, this._$AB = t, this._$AM = i, this.options = s, this._$Cv = (s == null ? void 0 : s.isConnected) ?? !0; + } + get parentNode() { + let e = this._$AA.parentNode; + const t = this._$AM; + return t !== void 0 && (e == null ? void 0 : e.nodeType) === 11 && (e = t.parentNode), e; + } + get startNode() { + return this._$AA; + } + get endNode() { + return this._$AB; + } + _$AI(e, t = this) { + e = L(this, e, t), F(e) ? e === m || e == null || e === "" ? (this._$AH !== m && this._$AR(), this._$AH = m) : e !== this._$AH && e !== N && this._(e) : e._$litType$ !== void 0 ? this.$(e) : e.nodeType !== void 0 ? this.T(e) : ht(e) ? this.k(e) : this._(e); + } + O(e) { + return this._$AA.parentNode.insertBefore(e, this._$AB); + } + T(e) { + this._$AH !== e && (this._$AR(), this._$AH = this.O(e)); + } + _(e) { + this._$AH !== m && F(this._$AH) ? this._$AA.nextSibling.data = e : this.T(O.createTextNode(e)), this._$AH = e; + } + $(e) { + var n; + const { values: t, _$litType$: i } = e, s = typeof i == "number" ? this._$AC(e) : (i.el === void 0 && (i.el = q.createElement(Je(i.h, i.h[0]), this.options)), i); + if (((n = this._$AH) == null ? void 0 : n._$AD) === s) this._$AH.p(t); + else { + const o = new gt(s, this), a = o.u(this.options); + o.p(t), this.T(a), this._$AH = o; + } + } + _$AC(e) { + let t = Me.get(e.strings); + return t === void 0 && Me.set(e.strings, t = new q(e)), t; + } + k(e) { + we(this._$AH) || (this._$AH = [], this._$AR()); + const t = this._$AH; + let i, s = 0; + for (const n of e) s === t.length ? t.push(i = new Y(this.O(I()), this.O(I()), this, this.options)) : i = t[s], i._$AI(n), s++; + s < t.length && (this._$AR(i && i._$AB.nextSibling, s), t.length = s); + } + _$AR(e = this._$AA.nextSibling, t) { + var i; + for ((i = this._$AP) == null ? void 0 : i.call(this, !1, !0, t); e !== this._$AB; ) { + const s = e.nextSibling; + e.remove(), e = s; + } + } + setConnected(e) { + var t; + this._$AM === void 0 && (this._$Cv = e, (t = this._$AP) == null || t.call(this, e)); + } +} +class ie { + get tagName() { + return this.element.tagName; + } + get _$AU() { + return this._$AM._$AU; + } + constructor(e, t, i, s, n) { + this.type = 1, this._$AH = m, this._$AN = void 0, this.element = e, this.name = t, this._$AM = s, this.options = n, i.length > 2 || i[0] !== "" || i[1] !== "" ? (this._$AH = Array(i.length - 1).fill(new String()), this.strings = i) : this._$AH = m; + } + _$AI(e, t = this, i, s) { + const n = this.strings; + let o = !1; + if (n === void 0) e = L(this, e, t, 0), o = !F(e) || e !== this._$AH && e !== N, o && (this._$AH = e); + else { + const a = e; + let c, h; + for (e = n[0], c = 0; c < n.length - 1; c++) h = L(this, a[i + c], t, c), h === N && (h = this._$AH[c]), o || (o = !F(h) || h !== this._$AH[c]), h === m ? e = m : e !== m && (e += (h ?? "") + n[c + 1]), this._$AH[c] = h; + } + o && !s && this.j(e); + } + j(e) { + e === m ? this.element.removeAttribute(this.name) : this.element.setAttribute(this.name, e ?? ""); + } +} +class ft extends ie { + constructor() { + super(...arguments), this.type = 3; + } + j(e) { + this.element[this.name] = e === m ? void 0 : e; + } +} +class mt extends ie { + constructor() { + super(...arguments), this.type = 4; + } + j(e) { + this.element.toggleAttribute(this.name, !!e && e !== m); + } +} +class bt extends ie { + constructor(e, t, i, s, n) { + super(e, t, i, s, n), this.type = 5; + } + _$AI(e, t = this) { + if ((e = L(this, e, t, 0) ?? m) === N) return; + const i = this._$AH, s = e === m && i !== m || e.capture !== i.capture || e.once !== i.once || e.passive !== i.passive, n = e !== m && (i === m || s); + s && this.element.removeEventListener(this.name, this, i), n && this.element.addEventListener(this.name, this, e), this._$AH = e; + } + handleEvent(e) { + var t; + typeof this._$AH == "function" ? this._$AH.call(((t = this.options) == null ? void 0 : t.host) ?? this.element, e) : this._$AH.handleEvent(e); + } +} +class yt { + constructor(e, t, i) { + this.element = e, this.type = 6, this._$AN = void 0, this._$AM = t, this.options = i; + } + get _$AU() { + return this._$AM._$AU; + } + _$AI(e) { + L(this, e); + } +} +const be = D.litHtmlPolyfillSupport; +be == null || be(q, Y), (D.litHtmlVersions ?? (D.litHtmlVersions = [])).push("3.3.1"); +const xt = (r, e, t) => { + const i = (t == null ? void 0 : t.renderBefore) ?? e; + let s = i._$litPart$; + if (s === void 0) { + const n = (t == null ? void 0 : t.renderBefore) ?? null; + i._$litPart$ = s = new Y(e.insertBefore(I(), n), n, void 0, t ?? {}); + } + return s._$AI(r), s; +}; +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +const k = globalThis; +class E extends U { + constructor() { + super(...arguments), this.renderOptions = { host: this }, this._$Do = void 0; + } + createRenderRoot() { + var t; + const e = super.createRenderRoot(); + return (t = this.renderOptions).renderBefore ?? (t.renderBefore = e.firstChild), e; + } + update(e) { + const t = this.render(); + this.hasUpdated || (this.renderOptions.isConnected = this.isConnected), super.update(e), this._$Do = xt(t, this.renderRoot, this.renderOptions); + } + connectedCallback() { + var e; + super.connectedCallback(), (e = this._$Do) == null || e.setConnected(!0); + } + disconnectedCallback() { + var e; + super.disconnectedCallback(), (e = this._$Do) == null || e.setConnected(!1); + } + render() { + return N; + } +} +var qe; +E._$litElement$ = !0, E.finalized = !0, (qe = k.litElementHydrateSupport) == null || qe.call(k, { LitElement: E }); +const ye = k.litElementPolyfillSupport; +ye == null || ye({ LitElement: E }); +(k.litElementVersions ?? (k.litElementVersions = [])).push("4.2.1"); +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +const ne = (r) => (e, t) => { + t !== void 0 ? t.addInitializer((() => { + customElements.define(r, e); + })) : customElements.define(r, e); +}; +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +const vt = { attribute: !0, type: String, converter: te, reflect: !1, hasChanged: $e }, $t = (r = vt, e, t) => { + const { kind: i, metadata: s } = t; + let n = globalThis.litPropertyMetadata.get(s); + if (n === void 0 && globalThis.litPropertyMetadata.set(s, n = /* @__PURE__ */ new Map()), i === "setter" && ((r = Object.create(r)).wrapped = !0), n.set(t.name, r), i === "accessor") { + const { name: o } = t; + return { set(a) { + const c = e.get.call(this); + e.set.call(this, a), this.requestUpdate(o, c, r); + }, init(a) { + return a !== void 0 && this.C(o, void 0, r, a), a; + } }; + } + if (i === "setter") { + const { name: o } = t; + return function(a) { + const c = this[o]; + e.call(this, a), this.requestUpdate(o, c, r); + }; + } + throw Error("Unsupported decorator location: " + i); +}; +function b(r) { + return (e, t) => typeof t == "object" ? $t(r, e, t) : ((i, s, n) => { + const o = s.hasOwnProperty(n); + return s.constructor.createProperty(n, i), o ? Object.getOwnPropertyDescriptor(s, n) : void 0; + })(r, e, t); +} +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +function V(r) { + return b({ ...r, state: !0, attribute: !1 }); +} +const Be = { + en: { + card: { + noDataMessage: "No OER data available", + untitledMessage: "Untitled Resource", + licenseLabel: "License:", + noLicenseMessage: "No license information" + }, + list: { + loadingMessage: "Loading resources...", + emptyTitle: "No resources found", + emptyMessage: "Try adjusting your search criteria or check back later." + }, + pagination: { + firstButtonText: "First", + previousButtonText: "Previous", + nextButtonText: "Next", + lastButtonText: "Last", + showingPagesText: "Showing", + totalResourcesText: "total resources", + pageOfText: "Page", + ofText: "of" + }, + search: { + headerTitle: "Search OER", + keywordsLabel: "Keyword search", + languageLabel: "Language", + licenseLabel: "License", + freeForUseLabel: "Free for use", + sourceLabel: "Source", + typeLabel: "Resource type", + keywordsPlaceholder: "Search by keyword...", + languagePlaceholder: "e.g., en, de, fr", + licensePlaceholder: "License URI...", + typePlaceholder: "e.g., image, video, document", + searchingText: "Searching...", + searchButtonText: "Search", + clearButtonText: "Clear", + anyOptionText: "Any", + yesOptionText: "Yes", + noOptionText: "No", + firstButtonText: "First", + previousButtonText: "Previous", + nextButtonText: "Next", + lastButtonText: "Last", + showingPagesText: "Showing", + totalResourcesText: "total resources", + pageOfText: "Page", + advancedFiltersShowText: "Show advanced filters", + advancedFiltersHideText: "Hide advanced filters", + errorMessage: "An error occurred" + } + }, + de: { + card: { + noDataMessage: "Keine OER-Daten verfügbar", + untitledMessage: "Unbenannte Ressource", + licenseLabel: "Lizenz:", + noLicenseMessage: "Keine Lizenzinformationen" + }, + list: { + loadingMessage: "Ressourcen werden geladen...", + emptyTitle: "Keine Ressourcen gefunden", + emptyMessage: "Passen Sie Ihre Suchkriterien an oder versuchen Sie es später erneut." + }, + pagination: { + firstButtonText: "Erste", + previousButtonText: "Zurück", + nextButtonText: "Weiter", + lastButtonText: "Letzte", + showingPagesText: "Angezeigt", + totalResourcesText: "Ressourcen insgesamt", + pageOfText: "Seite", + ofText: "von" + }, + search: { + headerTitle: "OER suchen", + keywordsLabel: "Stichwortsuche", + languageLabel: "Sprache", + licenseLabel: "Lizenz", + freeForUseLabel: "Kostenlos verfügbar", + sourceLabel: "Quelle", + typeLabel: "Ressourcentyp", + keywordsPlaceholder: "Nach einem Stichwort suchen...", + languagePlaceholder: "z.B. de, en, fr", + licensePlaceholder: "Lizenz-URI...", + typePlaceholder: "z.B. image, video, document", + searchingText: "Suche läuft...", + searchButtonText: "Suchen", + clearButtonText: "Zurücksetzen", + anyOptionText: "Alle", + yesOptionText: "Ja", + noOptionText: "Nein", + firstButtonText: "Erste", + previousButtonText: "Zurück", + nextButtonText: "Weiter", + lastButtonText: "Letzte", + showingPagesText: "Angezeigt", + totalResourcesText: "Ressourcen insgesamt", + pageOfText: "Seite", + advancedFiltersShowText: "Erweiterte Filter anzeigen", + advancedFiltersHideText: "Erweiterte Filter ausblenden", + errorMessage: "Ein Fehler ist aufgetreten" + } + } +}; +function oe(r) { + return Be[r] || Be.en; +} +function wt(r) { + return oe(r).card; +} +function _t(r) { + return oe(r).list; +} +function St(r) { + return oe(r).search; +} +function At(r) { + return oe(r).pagination; +} +const X = "nostr", Ge = [ + { + uri: "https://creativecommons.org/publicdomain/zero/1.0/", + shortName: "CC0 1.0" + }, + { + uri: "https://creativecommons.org/licenses/by/4.0/", + shortName: "CC BY 4.0" + }, + { + uri: "https://creativecommons.org/licenses/by-sa/4.0/", + shortName: "CC BY-SA 4.0" + }, + { + uri: "https://creativecommons.org/licenses/by-nd/4.0/", + shortName: "CC BY-ND 4.0" + }, + { + uri: "https://creativecommons.org/licenses/by-nc/4.0/", + shortName: "CC BY-NC 4.0" + }, + { + uri: "https://creativecommons.org/licenses/by-nc-sa/4.0/", + shortName: "CC BY-NC-SA 4.0" + }, + { + uri: "https://creativecommons.org/licenses/by-nc-nd/4.0/", + shortName: "CC BY-NC-ND 4.0" + }, + { + uri: "https://creativecommons.org/licenses/by/3.0/", + shortName: "CC BY 3.0" + }, + { + uri: "https://creativecommons.org/licenses/by-sa/3.0/", + shortName: "CC BY-SA 3.0" + }, + { + uri: "https://creativecommons.org/licenses/by-nd/3.0/", + shortName: "CC BY-ND 3.0" + }, + { + uri: "https://creativecommons.org/licenses/by-nc/3.0/", + shortName: "CC BY-NC 3.0" + }, + { + uri: "https://creativecommons.org/licenses/by-nc-sa/3.0/", + shortName: "CC BY-NC-SA 3.0" + }, + { + uri: "https://creativecommons.org/licenses/by-nc-nd/3.0/", + shortName: "CC BY-NC-ND 3.0" + } +]; +function Et(r) { + const e = Ge.find((t) => t.uri === r); + return e ? e.shortName : null; +} +const Tt = [ + { code: "en", label: "English" }, + { code: "de", label: "Deutsch" }, + { code: "fr", label: "Français" }, + { code: "it", label: "Italiano" }, + { code: "es", label: "Español" }, + { code: "pt", label: "Português" } +], Pt = [ + { value: "image", label: "Image" }, + { value: "video", label: "Video" }, + { value: "audio", label: "Audio" }, + { value: "text", label: "Text" }, + { value: "application/pdf", label: "PDF" } +]; +function _e(r, e) { + return !r || r.length <= e ? r : r.slice(0, e - 3) + "..."; +} +function Ct(r) { + return _e(r, 40); +} +function kt(r) { + return _e(r, 60); +} +function Ot(r) { + return _e(r, 20); +} +function zt(r) { + return r.slice(0, 4).map((e) => { + const t = typeof e == "string" ? e : String(e); + return Ot(t); + }); +} +const Rt = se` + :host { + display: block; + width: 100%; + box-sizing: border-box; + } + + .card { + border: 1px solid var(--border-color, rgba(0, 0, 0, 0.1)); + border-radius: 8px; + overflow: hidden; + background: var(--background-card); + box-shadow: 0 2px 4px var(--shadow-color, rgba(0, 0, 0, 0.05)); + transition: + box-shadow 0.3s ease, + transform 0.3s ease; + display: flex; + flex-direction: column; + height: 100%; + } + + .card:hover { + box-shadow: 0 8px 16px var(--shadow-color-hover, rgba(0, 0, 0, 0.15)); + transform: translateY(-2px); + } + + .thumbnail-container { + width: 100%; + aspect-ratio: 16 / 9; + overflow: hidden; + background: var(--background-muted, #f5f5f5); + position: relative; + cursor: pointer; + } + + .thumbnail { + width: 100%; + height: 100%; + object-fit: cover; + transition: transform 0.2s ease; + } + + .thumbnail-container:hover .thumbnail { + transform: scale(1.05); + } + + .placeholder { + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + background: linear-gradient(135deg, var(--primary-color) 0%, var(--secondary-color) 100%); + color: white; + font-size: 48px; + } + + .content { + padding: 16px; + flex: 1; + display: flex; + flex-direction: column; + } + + .title { + font-size: 16px; + font-weight: 600; + margin: 0 0 8px 0; + color: var(--text-primary); + line-height: 1.4; + overflow: hidden; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + } + + .title a { + color: var(--text-primary); + text-decoration: none; + } + + .title a:hover { + color: var(--primary-color); + text-decoration: underline; + } + + .description { + font-size: 14px; + color: var(--text-secondary); + margin: 0 0 12px 0; + line-height: 1.5; + overflow: hidden; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + flex: 1; + } + + .metadata { + display: flex; + flex-direction: column; + gap: 8px; + margin-top: auto; + } + + .license { + font-size: 12px; + color: var(--text-secondary); + } + + .license a { + color: var(--primary-color); + text-decoration: none; + font-weight: 500; + } + + .license a:hover { + text-decoration: underline; + } + + .keywords { + display: flex; + flex-wrap: wrap; + gap: 6px; + } + + .keyword { + background: var(--button-secondary-bg, rgba(0, 0, 0, 0.05)); + padding: 4px 8px; + border-radius: 4px; + font-size: 11px; + color: var(--text-secondary); + } + + .attribution { + font-size: 10px; + color: var(--text-muted); + line-height: 1.4; + margin-top: 4px; + padding-top: 8px; + border-top: 1px solid var(--border-color-subtle, rgba(0, 0, 0, 0.05)); + } + + .no-data { + color: var(--text-muted); + font-style: italic; + font-size: 12px; + } +`; +var Ut = Object.defineProperty, Nt = Object.getOwnPropertyDescriptor, Se = (r, e, t, i) => { + for (var s = i > 1 ? void 0 : i ? Nt(e, t) : e, n = r.length - 1, o; n >= 0; n--) + (o = r[n]) && (s = (i ? o(e, t, s) : o(s)) || s); + return i && s && Ut(e, t, s), s; +}; +let W = class extends E { + constructor() { + super(...arguments), this.oer = null, this.language = "en"; + } + get t() { + return wt(this.language); + } + handleImageClick() { + this.oer && this.dispatchEvent( + new CustomEvent("card-click", { + detail: { oer: this.oer }, + bubbles: !0, + composed: !0 + }) + ); + } + getLicenseName(r) { + if (!r) return "Unknown License"; + const e = typeof r == "string" ? r : JSON.stringify(r), t = Et(e); + return t || (e.includes("creativecommons.org") ? "Creative Commons" : "License"); + } + render() { + var p, l, d, g, w; + if (!this.oer) + return u` +
+
+

${this.t.noDataMessage}

+
+
+ `; + const r = ((p = this.oer.images) == null ? void 0 : p.small) ?? this.oer.url ?? null, e = Ct( + this.oer.name || ((l = this.oer.amb_metadata) == null ? void 0 : l.name) || this.t.untitledMessage + ), t = ((d = this.oer.amb_metadata) == null ? void 0 : d.description) || this.oer.description, i = typeof t == "string" ? t : "", s = i ? kt(i) : "", n = this.oer.keywords || ((g = this.oer.amb_metadata) == null ? void 0 : g.keywords) || [], o = zt(n), a = this.oer.license_uri || ((w = this.oer.amb_metadata) == null ? void 0 : w.license), c = this.oer.attribution, h = this.oer.foreign_landing_url; + return u` +
+
+ ${r ? u`${this.oer.file_alt || e}` : u`
📚
`} +
+
+

+ ${h ? u`${e}` : e} +

+ ${s ? u`

${s}

` : ""} + +
+
+ `; + } +}; +W.styles = Rt; +Se([ + b({ type: Object }) +], W.prototype, "oer", 2); +Se([ + b({ type: String }) +], W.prototype, "language", 2); +W = Se([ + ne("oer-card") +], W); +const Lt = se` + :host { + display: block; + width: 100%; + box-sizing: border-box; + } + + .list-container { + width: 100%; + margin-bottom: 24px; + } + + .grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); + gap: 18px; + width: 100%; + } + + .empty-state { + text-align: center; + padding: 48px 24px; + color: var(--text-secondary); + } + + .empty-icon { + font-size: 64px; + margin-bottom: 16px; + } + + .empty-title { + font-size: 20px; + font-weight: 600; + margin: 0 0 8px 0; + color: var(--text-primary); + } + + .empty-message { + font-size: 14px; + margin: 0; + color: var(--text-secondary); + } + + .loading { + text-align: center; + padding: 48px 24px; + color: var(--text-secondary); + } + + .loading-spinner { + display: inline-block; + width: 40px; + height: 40px; + border: 4px solid var(--spinner-track-color, #f3f3f3); + border-top: 4px solid var(--primary-color); + border-radius: 50%; + animation: spin 1s linear infinite; + margin-bottom: 16px; + } + + @keyframes spin { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } + } + + .error { + text-align: center; + padding: 48px 24px; + color: var(--error-color, #d32f2f); + } + + .error-icon { + font-size: 48px; + margin-bottom: 16px; + } + + .error-message { + font-size: 14px; + margin: 0; + } +`; +var jt = Object.defineProperty, Mt = Object.getOwnPropertyDescriptor, K = (r, e, t, i) => { + for (var s = i > 1 ? void 0 : i ? Mt(e, t) : e, n = r.length - 1, o; n >= 0; n--) + (o = r[n]) && (s = (i ? o(e, t, s) : o(s)) || s); + return i && s && jt(e, t, s), s; +}; +let z = class extends E { + constructor() { + super(...arguments), this.oers = [], this.loading = !1, this.error = null, this.language = "en"; + } + get t() { + return _t(this.language); + } + render() { + return this.loading ? u` +
+
+

${this.t.loadingMessage}

+
+ ` : this.error ? u` +
+
⚠️
+

${this.error}

+
+ ` : !this.oers || this.oers.length === 0 ? u` +
+
📭
+

${this.t.emptyTitle}

+

${this.t.emptyMessage}

+
+ ` : u` +
+
+ ${this.oers.map( + (r) => u` ` + )} +
+
+ `; + } +}; +z.styles = Lt; +K([ + b({ type: Array }) +], z.prototype, "oers", 2); +K([ + b({ type: Boolean }) +], z.prototype, "loading", 2); +K([ + b({ type: String }) +], z.prototype, "error", 2); +K([ + b({ type: String }) +], z.prototype, "language", 2); +z = K([ + ne("oer-list") +], z); +const Bt = /\{[^{}]+\}/g, Ht = () => { + var r, e; + return typeof process == "object" && Number.parseInt((e = (r = process == null ? void 0 : process.versions) == null ? void 0 : r.node) == null ? void 0 : e.substring(0, 2)) >= 18 && process.versions.undici; +}; +function Dt() { + return Math.random().toString(36).slice(2, 11); +} +function It(r) { + let { + baseUrl: e = "", + Request: t = globalThis.Request, + fetch: i = globalThis.fetch, + querySerializer: s, + bodySerializer: n, + headers: o, + requestInitExt: a = void 0, + ...c + } = { ...r }; + a = Ht() ? a : void 0, e = Ie(e); + const h = []; + async function p(l, d) { + const { + baseUrl: g, + fetch: w = i, + Request: Ae = t, + headers: Ee, + params: R = {}, + parseAs: ce = "json", + querySerializer: J, + bodySerializer: Te = n ?? qt, + body: Pe, + ...de + } = d || {}; + let he = e; + g && (he = Ie(g) ?? e); + let pe = typeof s == "function" ? s : He(s); + J && (pe = typeof J == "function" ? J : He({ + ...typeof s == "object" ? s : {}, + ...J + })); + const ue = Pe === void 0 ? void 0 : Te( + Pe, + // Note: we declare mergeHeaders() both here and below because it’s a bit of a chicken-or-egg situation: + // bodySerializer() needs all headers so we aren’t dropping ones set by the user, however, + // the result of this ALSO sets the lowest-priority content-type header. So we re-merge below, + // setting the content-type at the very beginning to be overwritten. + // Lastly, based on the way headers work, it’s not a simple “present-or-not” check becauase null intentionally un-sets headers. + De(o, Ee, R.header) + ), Xe = De( + // with no body, we should not to set Content-Type + ue === void 0 || // if serialized body is FormData; browser will correctly set Content-Type & boundary expression + ue instanceof FormData ? {} : { + "Content-Type": "application/json" + }, + o, + Ee, + R.header + ), et = { + redirect: "follow", + ...c, + ...de, + body: ue, + headers: Xe + }; + let G, Z, _ = new t( + Wt(l, { baseUrl: he, params: R, querySerializer: pe }), + et + ), f; + for (const v in de) + v in _ || (_[v] = de[v]); + if (h.length) { + G = Dt(), Z = Object.freeze({ + baseUrl: he, + fetch: w, + parseAs: ce, + querySerializer: pe, + bodySerializer: Te + }); + for (const v of h) + if (v && typeof v == "object" && typeof v.onRequest == "function") { + const y = await v.onRequest({ + request: _, + schemaPath: l, + params: R, + options: Z, + id: G + }); + if (y) + if (y instanceof t) + _ = y; + else if (y instanceof Response) { + f = y; + break; + } else + throw new Error("onRequest: must return new Request() or Response() when modifying the request"); + } + } + if (!f) { + try { + f = await w(_, a); + } catch (v) { + let y = v; + if (h.length) + for (let T = h.length - 1; T >= 0; T--) { + const Q = h[T]; + if (Q && typeof Q == "object" && typeof Q.onError == "function") { + const M = await Q.onError({ + request: _, + error: y, + schemaPath: l, + params: R, + options: Z, + id: G + }); + if (M) { + if (M instanceof Response) { + y = void 0, f = M; + break; + } + if (M instanceof Error) { + y = M; + continue; + } + throw new Error("onError: must return new Response() or instance of Error"); + } + } + } + if (y) + throw y; + } + if (h.length) + for (let v = h.length - 1; v >= 0; v--) { + const y = h[v]; + if (y && typeof y == "object" && typeof y.onResponse == "function") { + const T = await y.onResponse({ + request: _, + response: f, + schemaPath: l, + params: R, + options: Z, + id: G + }); + if (T) { + if (!(T instanceof Response)) + throw new Error("onResponse: must return new Response() when modifying the response"); + f = T; + } + } + } + } + if (f.status === 204 || _.method === "HEAD" || f.headers.get("Content-Length") === "0") + return f.ok ? { data: void 0, response: f } : { error: void 0, response: f }; + if (f.ok) + return ce === "stream" ? { data: f.body, response: f } : { data: await f[ce](), response: f }; + let ge = await f.text(); + try { + ge = JSON.parse(ge); + } catch { + } + return { error: ge, response: f }; + } + return { + request(l, d, g) { + return p(d, { ...g, method: l.toUpperCase() }); + }, + /** Call a GET endpoint */ + GET(l, d) { + return p(l, { ...d, method: "GET" }); + }, + /** Call a PUT endpoint */ + PUT(l, d) { + return p(l, { ...d, method: "PUT" }); + }, + /** Call a POST endpoint */ + POST(l, d) { + return p(l, { ...d, method: "POST" }); + }, + /** Call a DELETE endpoint */ + DELETE(l, d) { + return p(l, { ...d, method: "DELETE" }); + }, + /** Call a OPTIONS endpoint */ + OPTIONS(l, d) { + return p(l, { ...d, method: "OPTIONS" }); + }, + /** Call a HEAD endpoint */ + HEAD(l, d) { + return p(l, { ...d, method: "HEAD" }); + }, + /** Call a PATCH endpoint */ + PATCH(l, d) { + return p(l, { ...d, method: "PATCH" }); + }, + /** Call a TRACE endpoint */ + TRACE(l, d) { + return p(l, { ...d, method: "TRACE" }); + }, + /** Register middleware */ + use(...l) { + for (const d of l) + if (d) { + if (typeof d != "object" || !("onRequest" in d || "onResponse" in d || "onError" in d)) + throw new Error("Middleware must be an object with one of `onRequest()`, `onResponse() or `onError()`"); + h.push(d); + } + }, + /** Unregister middleware */ + eject(...l) { + for (const d of l) { + const g = h.indexOf(d); + g !== -1 && h.splice(g, 1); + } + } + }; +} +function ae(r, e, t) { + if (e == null) + return ""; + if (typeof e == "object") + throw new Error( + "Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these." + ); + return `${r}=${(t == null ? void 0 : t.allowReserved) === !0 ? e : encodeURIComponent(e)}`; +} +function Ze(r, e, t) { + if (!e || typeof e != "object") + return ""; + const i = [], s = { + simple: ",", + label: ".", + matrix: ";" + }[t.style] || "&"; + if (t.style !== "deepObject" && t.explode === !1) { + for (const a in e) + i.push(a, t.allowReserved === !0 ? e[a] : encodeURIComponent(e[a])); + const o = i.join(","); + switch (t.style) { + case "form": + return `${r}=${o}`; + case "label": + return `.${o}`; + case "matrix": + return `;${r}=${o}`; + default: + return o; + } + } + for (const o in e) { + const a = t.style === "deepObject" ? `${r}[${o}]` : o; + i.push(ae(a, e[o], t)); + } + const n = i.join(s); + return t.style === "label" || t.style === "matrix" ? `${s}${n}` : n; +} +function Qe(r, e, t) { + if (!Array.isArray(e)) + return ""; + if (t.explode === !1) { + const n = { form: ",", spaceDelimited: "%20", pipeDelimited: "|" }[t.style] || ",", o = (t.allowReserved === !0 ? e : e.map((a) => encodeURIComponent(a))).join(n); + switch (t.style) { + case "simple": + return o; + case "label": + return `.${o}`; + case "matrix": + return `;${r}=${o}`; + // case "spaceDelimited": + // case "pipeDelimited": + default: + return `${r}=${o}`; + } + } + const i = { simple: ",", label: ".", matrix: ";" }[t.style] || "&", s = []; + for (const n of e) + t.style === "simple" || t.style === "label" ? s.push(t.allowReserved === !0 ? n : encodeURIComponent(n)) : s.push(ae(r, n, t)); + return t.style === "label" || t.style === "matrix" ? `${i}${s.join(i)}` : s.join(i); +} +function He(r) { + return function(t) { + const i = []; + if (t && typeof t == "object") + for (const s in t) { + const n = t[s]; + if (n != null) { + if (Array.isArray(n)) { + if (n.length === 0) + continue; + i.push( + Qe(s, n, { + style: "form", + explode: !0, + ...r == null ? void 0 : r.array, + allowReserved: (r == null ? void 0 : r.allowReserved) || !1 + }) + ); + continue; + } + if (typeof n == "object") { + i.push( + Ze(s, n, { + style: "deepObject", + explode: !0, + ...r == null ? void 0 : r.object, + allowReserved: (r == null ? void 0 : r.allowReserved) || !1 + }) + ); + continue; + } + i.push(ae(s, n, r)); + } + } + return i.join("&"); + }; +} +function Ft(r, e) { + let t = r; + for (const i of r.match(Bt) ?? []) { + let s = i.substring(1, i.length - 1), n = !1, o = "simple"; + if (s.endsWith("*") && (n = !0, s = s.substring(0, s.length - 1)), s.startsWith(".") ? (o = "label", s = s.substring(1)) : s.startsWith(";") && (o = "matrix", s = s.substring(1)), !e || e[s] === void 0 || e[s] === null) + continue; + const a = e[s]; + if (Array.isArray(a)) { + t = t.replace(i, Qe(s, a, { style: o, explode: n })); + continue; + } + if (typeof a == "object") { + t = t.replace(i, Ze(s, a, { style: o, explode: n })); + continue; + } + if (o === "matrix") { + t = t.replace(i, `;${ae(s, a)}`); + continue; + } + t = t.replace(i, o === "label" ? `.${encodeURIComponent(a)}` : encodeURIComponent(a)); + } + return t; +} +function qt(r, e) { + return r instanceof FormData ? r : e && (e.get instanceof Function ? e.get("Content-Type") ?? e.get("content-type") : e["Content-Type"] ?? e["content-type"]) === "application/x-www-form-urlencoded" ? new URLSearchParams(r).toString() : JSON.stringify(r); +} +function Wt(r, e) { + var s; + let t = `${e.baseUrl}${r}`; + (s = e.params) != null && s.path && (t = Ft(t, e.params.path)); + let i = e.querySerializer(e.params.query ?? {}); + return i.startsWith("?") && (i = i.substring(1)), i && (t += `?${i}`), t; +} +function De(...r) { + const e = new Headers(); + for (const t of r) { + if (!t || typeof t != "object") + continue; + const i = t instanceof Headers ? t.entries() : Object.entries(t); + for (const [s, n] of i) + if (n === null) + e.delete(s); + else if (Array.isArray(n)) + for (const o of n) + e.append(s, o); + else n !== void 0 && e.set(s, n); + } + return e; +} +function Ie(r) { + return r.endsWith("/") ? r.substring(0, r.length - 1) : r; +} +function Fe(r, e) { + return It({ + baseUrl: r.replace(/\/$/, ""), + // Remove trailing slash + headers: e == null ? void 0 : e.headers, + fetch: e == null ? void 0 : e.fetch + }); +} +const Yt = se` + :host { + display: block; + width: 100%; + box-sizing: border-box; + } + + .search-wrapper { + display: flex; + flex-direction: column; + gap: 0; + } + + .slot-container { + margin-top: 24px; + } + + .slot-container:empty { + display: none; + margin-top: 0; + } + + .search-container { + background: var(--background-form); + border: 1px solid var(--border-color, rgba(0, 0, 0, 0.1)); + border-radius: 8px; + padding: 24px; + margin-bottom: 24px; + } + + .search-header { + margin: 0 0 16px 0; + font-size: 20px; + font-weight: 600; + color: var(--text-primary); + } + + .search-form { + display: flex; + flex-direction: column; + gap: 16px; + } + + .form-row { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: 12px; + } + + .form-group { + display: flex; + flex-direction: column; + gap: 6px; + } + + label { + font-size: 13px; + font-weight: 500; + color: var(--text-secondary); + } + + input, + select { + width: 100%; + padding: 10px 12px; + border: 1px solid var(--input-border-color, rgba(0, 0, 0, 0.15)); + border-radius: 6px; + font-size: 14px; + font-family: inherit; + transition: border-color 0.2s ease; + box-sizing: border-box; + background: var(--background-input, white); + color: var(--text-primary); + } + + input:focus, + select:focus { + outline: none; + border-color: var(--primary-color); + } + + .button-group { + display: flex; + gap: 12px; + margin-top: 8px; + } + + button { + padding: 10px 20px; + border: none; + border-radius: 6px; + font-size: 14px; + font-weight: 500; + cursor: pointer; + transition: all 0.2s ease; + font-family: inherit; + } + + .search-button { + background: var(--primary-color); + color: white; + flex: 1; + } + + .search-button:hover:not(:disabled) { + background: var(--primary-hover-color); + } + + .search-button:disabled { + background: #ccc; + cursor: not-allowed; + } + + .clear-button { + background: var(--button-secondary-bg, rgba(0, 0, 0, 0.05)); + color: var(--text-secondary); + flex: 0 0 auto; + } + + .clear-button:hover { + background: var(--button-secondary-hover-bg, rgba(0, 0, 0, 0.1)); + } + + .pagination { + display: flex; + justify-content: space-between; + align-items: center; + padding: 16px; + background: var(--background-form); + border: 1px solid var(--border-color, rgba(0, 0, 0, 0.1)); + border-radius: 8px; + margin-top: 24px; + gap: 12px; + flex-wrap: wrap; + } + + .pagination-info { + font-size: 14px; + color: var(--text-secondary); + flex: 1 1 100%; + text-align: center; + margin-bottom: 8px; + } + + .pagination-controls { + display: flex; + gap: 8px; + align-items: center; + flex-wrap: wrap; + justify-content: center; + flex: 1 1 100%; + } + + .page-button { + padding: 8px 12px; + background: var(--button-secondary-bg, rgba(0, 0, 0, 0.05)); + color: var(--text-primary); + min-width: 40px; + flex-shrink: 0; + } + + .page-button:hover:not(:disabled) { + background: var(--button-secondary-hover-bg, rgba(0, 0, 0, 0.1)); + } + + .page-button:disabled { + background: var(--button-secondary-bg, rgba(0, 0, 0, 0.05)); + color: var(--text-disabled, rgba(0, 0, 0, 0.3)); + cursor: not-allowed; + } + + .page-info { + font-size: 14px; + color: var(--text-secondary); + margin: 0 8px; + white-space: nowrap; + } + + /* Mobile responsive styles */ + @media (max-width: 768px) { + .search-container { + padding: 16px; + } + + .pagination { + padding: 12px; + flex-direction: column; + } + + .pagination-info { + margin-bottom: 12px; + font-size: 13px; + } + + .pagination-controls { + gap: 6px; + width: 100%; + } + + .page-button { + padding: 8px 10px; + font-size: 13px; + min-width: 60px; + flex: 1 1 auto; + } + + .page-info { + flex-basis: 100%; + text-align: center; + margin: 8px 0; + font-size: 13px; + } + + .button-group { + flex-direction: column; + } + + .search-button, + .clear-button { + width: 100%; + } + } + + @media (max-width: 480px) { + .search-container { + padding: 12px; + } + + .pagination { + padding: 10px; + } + + .pagination-info { + font-size: 12px; + } + + .pagination-controls { + gap: 4px; + } + + .page-button { + padding: 6px 8px; + font-size: 12px; + min-width: 50px; + } + + .page-info { + font-size: 12px; + margin: 6px 0; + } + + .form-row { + grid-template-columns: 1fr; + } + } + + .error-message { + background: #ffebee; + color: #c62828; + padding: 12px 16px; + border-radius: 6px; + margin-top: 12px; + font-size: 14px; + } + + .toggle-filters-button { + background: transparent; + color: var(--primary-color); + padding: 8px 0; + font-size: 14px; + font-weight: 500; + border: none; + cursor: pointer; + text-align: left; + display: flex; + align-items: center; + gap: 6px; + margin-bottom: 12px; + } + + .toggle-filters-button::before { + content: '▶'; + display: inline-block; + transition: transform 0.2s ease; + font-size: 10px; + } + + .toggle-filters-button:hover { + color: var(--primary-hover-color); + } + + .advanced-filters { + max-height: 0; + overflow: hidden; + transition: max-height 0.3s ease; + display: flex; + flex-direction: column; + gap: 16px; + } + + .advanced-filters.expanded { + max-height: 1000px; + } + + .advanced-filters.expanded ~ .toggle-filters-button::before, + .toggle-filters-button:has(~ .advanced-filters.expanded)::before { + transform: rotate(90deg); + } + + /* Fix the button state when filters are expanded */ + form:has(.advanced-filters.expanded) .toggle-filters-button::before { + transform: rotate(90deg); + } +`; +var Vt = Object.defineProperty, Kt = Object.getOwnPropertyDescriptor, $ = (r, e, t, i) => { + for (var s = i > 1 ? void 0 : i ? Kt(e, t) : e, n = r.length - 1, o; n >= 0; n--) + (o = r[n]) && (s = (i ? o(e, t, s) : o(s)) || s); + return i && s && Vt(e, t, s), s; +}; +let x = class extends E { + constructor() { + super(...arguments), this.apiUrl = "http://localhost:3000", this.language = "en", this.showTypeFilter = !0, this.pageSize = 20, this.availableSources = [], this.showSourceFilter = !0, this.client = null, this.searchParams = { + page: 1, + source: X + }, this.loading = !1, this.error = null, this.advancedFiltersExpanded = !1, this.handleSlottedPageChange = (r) => { + const e = r; + r.stopPropagation(), this.searchParams = { ...this.searchParams, page: e.detail.page }, this.performSearch(); + }; + } + get t() { + return St(this.language); + } + connectedCallback() { + super.connectedCallback(), this.client = Fe(this.apiUrl), this.searchParams = { + ...this.searchParams, + pageSize: this.pageSize + }, this.lockedType && (this.searchParams = { + ...this.searchParams, + type: this.lockedType + }), this.lockedSource && (this.searchParams = { + ...this.searchParams, + source: this.lockedSource + }), this.addEventListener("page-change", this.handleSlottedPageChange); + } + disconnectedCallback() { + super.disconnectedCallback(), this.removeEventListener("page-change", this.handleSlottedPageChange); + } + updated(r) { + if (super.updated(r), r.has("apiUrl") && (this.client = Fe(this.apiUrl)), r.has("pageSize") && (this.searchParams = { + ...this.searchParams, + pageSize: this.pageSize + }), r.has("lockedType")) + if (this.lockedType) + this.searchParams = { + ...this.searchParams, + type: this.lockedType + }; + else { + const { type: e, ...t } = this.searchParams; + this.searchParams = t; + } + r.has("lockedSource") && (this.lockedSource ? this.searchParams = { + ...this.searchParams, + source: this.lockedSource + } : this.searchParams = { + ...this.searchParams, + source: X + }); + } + async performSearch() { + if (this.client) { + this.loading = !0, this.error = null; + try { + const r = await this.client.GET("/api/v1/oer", { + params: { + query: this.searchParams + } + }); + if (r.error) { + const e = r.error.message ? Array.isArray(r.error.message) ? r.error.message.join(", ") : r.error.message : "Failed to fetch resources"; + throw new Error(e); + } + r.data && this.dispatchEvent( + new CustomEvent("search-results", { + detail: { + data: r.data.data, + meta: r.data.meta + }, + bubbles: !0, + composed: !0 + }) + ); + } catch (r) { + this.error = r instanceof Error ? r.message : this.t.errorMessage, this.dispatchEvent( + new CustomEvent("search-error", { + detail: { error: this.error }, + bubbles: !0, + composed: !0 + }) + ); + } finally { + this.loading = !1; + } + } + } + handleSubmit(r) { + r.preventDefault(), this.searchParams = { ...this.searchParams, page: 1 }, this.performSearch(); + } + handleClear() { + this.searchParams = { + page: 1, + pageSize: this.pageSize, + source: this.lockedSource || X + }, this.lockedType && (this.searchParams = { + ...this.searchParams, + type: this.lockedType + }), this.error = null, this.dispatchEvent( + new CustomEvent("search-cleared", { + bubbles: !0, + composed: !0 + }) + ); + } + handleInputChange(r) { + return (e) => { + const i = e.target.value.trim(); + if (i === "") { + const { [r]: s, ...n } = this.searchParams; + this.searchParams = n; + } else + this.searchParams = { + ...this.searchParams, + [r]: i + }; + }; + } + handleBooleanChange(r) { + return (e) => { + const i = e.target.value; + if (i === "") { + const { [r]: s, ...n } = this.searchParams; + this.searchParams = n; + } else + this.searchParams = { + ...this.searchParams, + [r]: i === "true" + }; + }; + } + toggleAdvancedFilters() { + this.advancedFiltersExpanded = !this.advancedFiltersExpanded; + } + render() { + return u` +
+
+

${this.t.headerTitle}

+
+
+ + +
+ + ${this.showTypeFilter && !this.lockedType ? u` +
+ + +
+ ` : ""} + + + +
+
+
+ + +
+ +
+ + +
+
+ + ${this.showSourceFilter && !this.lockedSource && this.availableSources.length > 0 ? u` +
+ + +
+ ` : ""} +
+ +
+ + +
+ + ${this.error ? u`
${this.error}
` : ""} +
+
+
+ +
+
+ `; + } +}; +x.styles = Yt; +$([ + b({ type: String, attribute: "api-url" }) +], x.prototype, "apiUrl", 2); +$([ + b({ type: String }) +], x.prototype, "language", 2); +$([ + b({ type: String, attribute: "locked-type" }) +], x.prototype, "lockedType", 2); +$([ + b({ type: Boolean, attribute: "show-type-filter" }) +], x.prototype, "showTypeFilter", 2); +$([ + b({ type: Number, attribute: "page-size" }) +], x.prototype, "pageSize", 2); +$([ + b({ type: Array, attribute: "available-sources" }) +], x.prototype, "availableSources", 2); +$([ + b({ type: String, attribute: "locked-source" }) +], x.prototype, "lockedSource", 2); +$([ + b({ type: Boolean, attribute: "show-source-filter" }) +], x.prototype, "showSourceFilter", 2); +$([ + V() +], x.prototype, "client", 2); +$([ + V() +], x.prototype, "searchParams", 2); +$([ + V() +], x.prototype, "loading", 2); +$([ + V() +], x.prototype, "error", 2); +$([ + V() +], x.prototype, "advancedFiltersExpanded", 2); +x = $([ + ne("oer-search") +], x); +const Jt = se` + :host { + display: block; + width: 100%; + } + + .pagination { + display: flex; + justify-content: space-between; + align-items: center; + padding: 16px; + background: var(--background-form); + border: 1px solid var(--border-color, rgba(0, 0, 0, 0.1)); + border-radius: 8px; + gap: 12px; + flex-wrap: wrap; + } + + .pagination-info { + font-size: 14px; + color: var(--text-secondary); + flex: 1 1 100%; + text-align: center; + margin-bottom: 8px; + } + + .pagination-controls { + display: flex; + gap: 8px; + align-items: center; + flex-wrap: wrap; + justify-content: center; + flex: 1 1 100%; + } + + .page-button { + padding: 8px 12px; + background: var(--button-secondary-bg, rgba(0, 0, 0, 0.05)); + color: var(--text-primary); + min-width: 40px; + flex-shrink: 0; + border: none; + border-radius: 6px; + font-size: 14px; + font-weight: 500; + cursor: pointer; + transition: all 0.2s ease; + font-family: inherit; + } + + .page-button:hover:not(:disabled) { + background: var(--button-secondary-hover-bg, rgba(0, 0, 0, 0.1)); + } + + .page-button:disabled { + background: var(--button-secondary-bg, rgba(0, 0, 0, 0.05)); + color: var(--text-disabled, rgba(0, 0, 0, 0.3)); + cursor: not-allowed; + } + + .page-info { + font-size: 14px; + color: var(--text-secondary); + margin: 0 8px; + white-space: nowrap; + } + + /* Mobile responsive styles */ + @media (max-width: 768px) { + .pagination { + padding: 12px; + flex-direction: column; + } + + .pagination-info { + margin-bottom: 12px; + font-size: 13px; + } + + .pagination-controls { + gap: 6px; + width: 100%; + } + + .page-button { + padding: 8px 10px; + font-size: 13px; + min-width: 60px; + flex: 1 1 auto; + } + + .page-info { + flex-basis: 100%; + text-align: center; + margin: 8px 0; + font-size: 13px; + } + } + + @media (max-width: 480px) { + .pagination { + padding: 10px; + } + + .pagination-info { + font-size: 12px; + } + + .pagination-controls { + gap: 4px; + } + + .page-button { + padding: 6px 8px; + font-size: 12px; + min-width: 50px; + } + + .page-info { + font-size: 12px; + margin: 6px 0; + } + } +`; +var Gt = Object.defineProperty, Zt = Object.getOwnPropertyDescriptor, le = (r, e, t, i) => { + for (var s = i > 1 ? void 0 : i ? Zt(e, t) : e, n = r.length - 1, o; n >= 0; n--) + (o = r[n]) && (s = (i ? o(e, t, s) : o(s)) || s); + return i && s && Gt(e, t, s), s; +}; +let j = class extends E { + constructor() { + super(...arguments), this.metadata = null, this.loading = !1, this.language = "en"; + } + get t() { + return At(this.language); + } + render() { + return this.metadata ? u` + + ` : ""; + } + handlePageChange(r) { + this.dispatchEvent( + new CustomEvent("page-change", { + detail: { page: r }, + bubbles: !0, + composed: !0 + }) + ); + } +}; +j.styles = Jt; +le([ + b({ type: Object }) +], j.prototype, "metadata", 2); +le([ + b({ type: Boolean }) +], j.prototype, "loading", 2); +le([ + b({ type: String }) +], j.prototype, "language", 2); +j = le([ + ne("oer-pagination") +], j); +const er = "0.0.1"; +export { + W as OerCardElement, + z as OerListElement, + x as OerSearchElement, + j as PaginationElement, + er as VERSION, + Fe as createOerClient, + wt as getCardTranslations, + _t as getListTranslations, + At as getPaginationTranslations, + St as getSearchTranslations, + oe as getTranslations, + zt as shortenLabels, + kt as truncateContent, + Ot as truncateLabel, + _e as truncateText, + Ct as truncateTitle +}; diff --git a/packages/oer-finder-plugin/dist/oer-plugin.umd.cjs b/packages/oer-finder-plugin/dist/oer-plugin.umd.cjs new file mode 100644 index 0000000..fca83fc --- /dev/null +++ b/packages/oer-finder-plugin/dist/oer-plugin.umd.cjs @@ -0,0 +1,911 @@ +(function(l,_){typeof exports=="object"&&typeof module<"u"?_(exports):typeof define=="function"&&define.amd?define(["exports"],_):(l=typeof globalThis<"u"?globalThis:l||self,_(l.OerPlugin={}))})(this,(function(l){"use strict";/** + * @license + * Copyright 2019 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */var tt;const _=globalThis,le=_.ShadowRoot&&(_.ShadyCSS===void 0||_.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,ce=Symbol(),Ee=new WeakMap;let Ae=class{constructor(e,t,s){if(this._$cssResult$=!0,s!==ce)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=e,this.t=t}get styleSheet(){let e=this.o;const t=this.t;if(le&&e===void 0){const s=t!==void 0&&t.length===1;s&&(e=Ee.get(t)),e===void 0&&((this.o=e=new CSSStyleSheet).replaceSync(this.cssText),s&&Ee.set(t,e))}return e}toString(){return this.cssText}};const it=i=>new Ae(typeof i=="string"?i:i+"",void 0,ce),K=(i,...e)=>{const t=i.length===1?i[0]:e.reduce(((s,r,n)=>s+(a=>{if(a._$cssResult$===!0)return a.cssText;if(typeof a=="number")return a;throw Error("Value passed to 'css' function must be a 'css' function result: "+a+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(r)+i[n+1]),i[0]);return new Ae(t,i,ce)},nt=(i,e)=>{if(le)i.adoptedStyleSheets=e.map((t=>t instanceof CSSStyleSheet?t:t.styleSheet));else for(const t of e){const s=document.createElement("style"),r=_.litNonce;r!==void 0&&s.setAttribute("nonce",r),s.textContent=t.cssText,i.appendChild(s)}},Te=le?i=>i:i=>i instanceof CSSStyleSheet?(e=>{let t="";for(const s of e.cssRules)t+=s.cssText;return it(t)})(i):i;/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */const{is:at,defineProperty:ot,getOwnPropertyDescriptor:lt,getOwnPropertyNames:ct,getOwnPropertySymbols:dt,getPrototypeOf:ht}=Object,S=globalThis,Pe=S.trustedTypes,pt=Pe?Pe.emptyScript:"",de=S.reactiveElementPolyfillSupport,j=(i,e)=>i,J={toAttribute(i,e){switch(e){case Boolean:i=i?pt:null;break;case Object:case Array:i=i==null?i:JSON.stringify(i)}return i},fromAttribute(i,e){let t=i;switch(e){case Boolean:t=i!==null;break;case Number:t=i===null?null:Number(i);break;case Object:case Array:try{t=JSON.parse(i)}catch{t=null}}return t}},he=(i,e)=>!at(i,e),Ce={attribute:!0,type:String,converter:J,reflect:!1,useDefault:!1,hasChanged:he};Symbol.metadata??(Symbol.metadata=Symbol("metadata")),S.litPropertyMetadata??(S.litPropertyMetadata=new WeakMap);let R=class extends HTMLElement{static addInitializer(e){this._$Ei(),(this.l??(this.l=[])).push(e)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(e,t=Ce){if(t.state&&(t.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(e)&&((t=Object.create(t)).wrapped=!0),this.elementProperties.set(e,t),!t.noAccessor){const s=Symbol(),r=this.getPropertyDescriptor(e,s,t);r!==void 0&&ot(this.prototype,e,r)}}static getPropertyDescriptor(e,t,s){const{get:r,set:n}=lt(this.prototype,e)??{get(){return this[t]},set(a){this[t]=a}};return{get:r,set(a){const o=r==null?void 0:r.call(this);n==null||n.call(this,a),this.requestUpdate(e,o,s)},configurable:!0,enumerable:!0}}static getPropertyOptions(e){return this.elementProperties.get(e)??Ce}static _$Ei(){if(this.hasOwnProperty(j("elementProperties")))return;const e=ht(this);e.finalize(),e.l!==void 0&&(this.l=[...e.l]),this.elementProperties=new Map(e.elementProperties)}static finalize(){if(this.hasOwnProperty(j("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(j("properties"))){const t=this.properties,s=[...ct(t),...dt(t)];for(const r of s)this.createProperty(r,t[r])}const e=this[Symbol.metadata];if(e!==null){const t=litPropertyMetadata.get(e);if(t!==void 0)for(const[s,r]of t)this.elementProperties.set(s,r)}this._$Eh=new Map;for(const[t,s]of this.elementProperties){const r=this._$Eu(t,s);r!==void 0&&this._$Eh.set(r,t)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(e){const t=[];if(Array.isArray(e)){const s=new Set(e.flat(1/0).reverse());for(const r of s)t.unshift(Te(r))}else e!==void 0&&t.push(Te(e));return t}static _$Eu(e,t){const s=t.attribute;return s===!1?void 0:typeof s=="string"?s:typeof e=="string"?e.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Em=null,this._$Ev()}_$Ev(){var e;this._$ES=new Promise((t=>this.enableUpdating=t)),this._$AL=new Map,this._$E_(),this.requestUpdate(),(e=this.constructor.l)==null||e.forEach((t=>t(this)))}addController(e){var t;(this._$EO??(this._$EO=new Set)).add(e),this.renderRoot!==void 0&&this.isConnected&&((t=e.hostConnected)==null||t.call(e))}removeController(e){var t;(t=this._$EO)==null||t.delete(e)}_$E_(){const e=new Map,t=this.constructor.elementProperties;for(const s of t.keys())this.hasOwnProperty(s)&&(e.set(s,this[s]),delete this[s]);e.size>0&&(this._$Ep=e)}createRenderRoot(){const e=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return nt(e,this.constructor.elementStyles),e}connectedCallback(){var e;this.renderRoot??(this.renderRoot=this.createRenderRoot()),this.enableUpdating(!0),(e=this._$EO)==null||e.forEach((t=>{var s;return(s=t.hostConnected)==null?void 0:s.call(t)}))}enableUpdating(e){}disconnectedCallback(){var e;(e=this._$EO)==null||e.forEach((t=>{var s;return(s=t.hostDisconnected)==null?void 0:s.call(t)}))}attributeChangedCallback(e,t,s){this._$AK(e,s)}_$ET(e,t){var n;const s=this.constructor.elementProperties.get(e),r=this.constructor._$Eu(e,s);if(r!==void 0&&s.reflect===!0){const a=(((n=s.converter)==null?void 0:n.toAttribute)!==void 0?s.converter:J).toAttribute(t,s.type);this._$Em=e,a==null?this.removeAttribute(r):this.setAttribute(r,a),this._$Em=null}}_$AK(e,t){var n,a;const s=this.constructor,r=s._$Eh.get(e);if(r!==void 0&&this._$Em!==r){const o=s.getPropertyOptions(r),d=typeof o.converter=="function"?{fromAttribute:o.converter}:((n=o.converter)==null?void 0:n.fromAttribute)!==void 0?o.converter:J;this._$Em=r;const p=d.fromAttribute(t,o.type);this[r]=p??((a=this._$Ej)==null?void 0:a.get(r))??p,this._$Em=null}}requestUpdate(e,t,s){var r;if(e!==void 0){const n=this.constructor,a=this[e];if(s??(s=n.getPropertyOptions(e)),!((s.hasChanged??he)(a,t)||s.useDefault&&s.reflect&&a===((r=this._$Ej)==null?void 0:r.get(e))&&!this.hasAttribute(n._$Eu(e,s))))return;this.C(e,t,s)}this.isUpdatePending===!1&&(this._$ES=this._$EP())}C(e,t,{useDefault:s,reflect:r,wrapped:n},a){s&&!(this._$Ej??(this._$Ej=new Map)).has(e)&&(this._$Ej.set(e,a??t??this[e]),n!==!0||a!==void 0)||(this._$AL.has(e)||(this.hasUpdated||s||(t=void 0),this._$AL.set(e,t)),r===!0&&this._$Em!==e&&(this._$Eq??(this._$Eq=new Set)).add(e))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(t){Promise.reject(t)}const e=this.scheduleUpdate();return e!=null&&await e,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){var s;if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??(this.renderRoot=this.createRenderRoot()),this._$Ep){for(const[n,a]of this._$Ep)this[n]=a;this._$Ep=void 0}const r=this.constructor.elementProperties;if(r.size>0)for(const[n,a]of r){const{wrapped:o}=a,d=this[n];o!==!0||this._$AL.has(n)||d===void 0||this.C(n,void 0,a,d)}}let e=!1;const t=this._$AL;try{e=this.shouldUpdate(t),e?(this.willUpdate(t),(s=this._$EO)==null||s.forEach((r=>{var n;return(n=r.hostUpdate)==null?void 0:n.call(r)})),this.update(t)):this._$EM()}catch(r){throw e=!1,this._$EM(),r}e&&this._$AE(t)}willUpdate(e){}_$AE(e){var t;(t=this._$EO)==null||t.forEach((s=>{var r;return(r=s.hostUpdated)==null?void 0:r.call(s)})),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(e)),this.updated(e)}_$EM(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(e){return!0}update(e){this._$Eq&&(this._$Eq=this._$Eq.forEach((t=>this._$ET(t,this[t])))),this._$EM()}updated(e){}firstUpdated(e){}};R.elementStyles=[],R.shadowRootOptions={mode:"open"},R[j("elementProperties")]=new Map,R[j("finalized")]=new Map,de==null||de({ReactiveElement:R}),(S.reactiveElementVersions??(S.reactiveElementVersions=[])).push("2.1.1");/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */const M=globalThis,G=M.trustedTypes,Oe=G?G.createPolicy("lit-html",{createHTML:i=>i}):void 0,ke="$lit$",E=`lit$${Math.random().toFixed(9).slice(2)}$`,ze="?"+E,ut=`<${ze}>`,P=document,B=()=>P.createComment(""),H=i=>i===null||typeof i!="object"&&typeof i!="function",pe=Array.isArray,gt=i=>pe(i)||typeof(i==null?void 0:i[Symbol.iterator])=="function",ue=`[ +\f\r]`,D=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,Re=/-->/g,Le=/>/g,C=RegExp(`>|${ue}(?:([^\\s"'>=/]+)(${ue}*=${ue}*(?:[^ +\f\r"'\`<>=]|("|')|))|$)`,"g"),Ne=/'/g,Ue=/"/g,je=/^(?:script|style|textarea|title)$/i,ft=i=>(e,...t)=>({_$litType$:i,strings:e,values:t}),g=ft(1),L=Symbol.for("lit-noChange"),m=Symbol.for("lit-nothing"),Me=new WeakMap,O=P.createTreeWalker(P,129);function Be(i,e){if(!pe(i)||!i.hasOwnProperty("raw"))throw Error("invalid template strings array");return Oe!==void 0?Oe.createHTML(e):e}const mt=(i,e)=>{const t=i.length-1,s=[];let r,n=e===2?"":e===3?"":"",a=D;for(let o=0;o"?(a=r??D,c=-1):u[1]===void 0?c=-2:(c=a.lastIndex-u[2].length,p=u[1],a=u[3]===void 0?C:u[3]==='"'?Ue:Ne):a===Ue||a===Ne?a=C:a===Re||a===Le?a=D:(a=C,r=void 0);const f=a===C&&i[o+1].startsWith("/>")?" ":"";n+=a===D?d+ut:c>=0?(s.push(p),d.slice(0,c)+ke+d.slice(c)+E+f):d+E+(c===-2?o:f)}return[Be(i,n+(i[t]||"")+(e===2?"":e===3?"":"")),s]};class I{constructor({strings:e,_$litType$:t},s){let r;this.parts=[];let n=0,a=0;const o=e.length-1,d=this.parts,[p,u]=mt(e,t);if(this.el=I.createElement(p,s),O.currentNode=this.el.content,t===2||t===3){const c=this.el.content.firstChild;c.replaceWith(...c.childNodes)}for(;(r=O.nextNode())!==null&&d.length0){r.textContent=G?G.emptyScript:"";for(let f=0;f2||s[0]!==""||s[1]!==""?(this._$AH=Array(s.length-1).fill(new String),this.strings=s):this._$AH=m}_$AI(e,t=this,s,r){const n=this.strings;let a=!1;if(n===void 0)e=N(this,e,t,0),a=!H(e)||e!==this._$AH&&e!==L,a&&(this._$AH=e);else{const o=e;let d,p;for(e=n[0],d=0;d{const s=(t==null?void 0:t.renderBefore)??e;let r=s._$litPart$;if(r===void 0){const n=(t==null?void 0:t.renderBefore)??null;s._$litPart$=r=new F(e.insertBefore(B(),n),n,void 0,t??{})}return r._$AI(i),r};/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */const k=globalThis;class A extends R{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){var t;const e=super.createRenderRoot();return(t=this.renderOptions).renderBefore??(t.renderBefore=e.firstChild),e}update(e){const t=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(e),this._$Do=wt(t,this.renderRoot,this.renderOptions)}connectedCallback(){var e;super.connectedCallback(),(e=this._$Do)==null||e.setConnected(!0)}disconnectedCallback(){var e;super.disconnectedCallback(),(e=this._$Do)==null||e.setConnected(!1)}render(){return L}}A._$litElement$=!0,A.finalized=!0,(tt=k.litElementHydrateSupport)==null||tt.call(k,{LitElement:A});const fe=k.litElementPolyfillSupport;fe==null||fe({LitElement:A}),(k.litElementVersions??(k.litElementVersions=[])).push("4.2.1");/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */const Q=i=>(e,t)=>{t!==void 0?t.addInitializer((()=>{customElements.define(i,e)})):customElements.define(i,e)};/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */const _t={attribute:!0,type:String,converter:J,reflect:!1,hasChanged:he},St=(i=_t,e,t)=>{const{kind:s,metadata:r}=t;let n=globalThis.litPropertyMetadata.get(r);if(n===void 0&&globalThis.litPropertyMetadata.set(r,n=new Map),s==="setter"&&((i=Object.create(i)).wrapped=!0),n.set(t.name,i),s==="accessor"){const{name:a}=t;return{set(o){const d=e.get.call(this);e.set.call(this,o),this.requestUpdate(a,d,i)},init(o){return o!==void 0&&this.C(a,void 0,i,o),o}}}if(s==="setter"){const{name:a}=t;return function(o){const d=this[a];e.call(this,o),this.requestUpdate(a,d,i)}}throw Error("Unsupported decorator location: "+s)};function b(i){return(e,t)=>typeof t=="object"?St(i,e,t):((s,r,n)=>{const a=r.hasOwnProperty(n);return r.constructor.createProperty(n,s),a?Object.getOwnPropertyDescriptor(r,n):void 0})(i,e,t)}/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */function q(i){return b({...i,state:!0,attribute:!1})}const He={en:{card:{noDataMessage:"No OER data available",untitledMessage:"Untitled Resource",licenseLabel:"License:",noLicenseMessage:"No license information"},list:{loadingMessage:"Loading resources...",emptyTitle:"No resources found",emptyMessage:"Try adjusting your search criteria or check back later."},pagination:{firstButtonText:"First",previousButtonText:"Previous",nextButtonText:"Next",lastButtonText:"Last",showingPagesText:"Showing",totalResourcesText:"total resources",pageOfText:"Page",ofText:"of"},search:{headerTitle:"Search OER",keywordsLabel:"Keyword search",languageLabel:"Language",licenseLabel:"License",freeForUseLabel:"Free for use",sourceLabel:"Source",typeLabel:"Resource type",keywordsPlaceholder:"Search by keyword...",languagePlaceholder:"e.g., en, de, fr",licensePlaceholder:"License URI...",typePlaceholder:"e.g., image, video, document",searchingText:"Searching...",searchButtonText:"Search",clearButtonText:"Clear",anyOptionText:"Any",yesOptionText:"Yes",noOptionText:"No",firstButtonText:"First",previousButtonText:"Previous",nextButtonText:"Next",lastButtonText:"Last",showingPagesText:"Showing",totalResourcesText:"total resources",pageOfText:"Page",advancedFiltersShowText:"Show advanced filters",advancedFiltersHideText:"Hide advanced filters",errorMessage:"An error occurred"}},de:{card:{noDataMessage:"Keine OER-Daten verfügbar",untitledMessage:"Unbenannte Ressource",licenseLabel:"Lizenz:",noLicenseMessage:"Keine Lizenzinformationen"},list:{loadingMessage:"Ressourcen werden geladen...",emptyTitle:"Keine Ressourcen gefunden",emptyMessage:"Passen Sie Ihre Suchkriterien an oder versuchen Sie es später erneut."},pagination:{firstButtonText:"Erste",previousButtonText:"Zurück",nextButtonText:"Weiter",lastButtonText:"Letzte",showingPagesText:"Angezeigt",totalResourcesText:"Ressourcen insgesamt",pageOfText:"Seite",ofText:"von"},search:{headerTitle:"OER suchen",keywordsLabel:"Stichwortsuche",languageLabel:"Sprache",licenseLabel:"Lizenz",freeForUseLabel:"Kostenlos verfügbar",sourceLabel:"Quelle",typeLabel:"Ressourcentyp",keywordsPlaceholder:"Nach einem Stichwort suchen...",languagePlaceholder:"z.B. de, en, fr",licensePlaceholder:"Lizenz-URI...",typePlaceholder:"z.B. image, video, document",searchingText:"Suche läuft...",searchButtonText:"Suchen",clearButtonText:"Zurücksetzen",anyOptionText:"Alle",yesOptionText:"Ja",noOptionText:"Nein",firstButtonText:"Erste",previousButtonText:"Zurück",nextButtonText:"Weiter",lastButtonText:"Letzte",showingPagesText:"Angezeigt",totalResourcesText:"Ressourcen insgesamt",pageOfText:"Seite",advancedFiltersShowText:"Erweiterte Filter anzeigen",advancedFiltersHideText:"Erweiterte Filter ausblenden",errorMessage:"Ein Fehler ist aufgetreten"}}};function W(i){return He[i]||He.en}function De(i){return W(i).card}function Ie(i){return W(i).list}function Fe(i){return W(i).search}function qe(i){return W(i).pagination}const X="nostr",We=[{uri:"https://creativecommons.org/publicdomain/zero/1.0/",shortName:"CC0 1.0"},{uri:"https://creativecommons.org/licenses/by/4.0/",shortName:"CC BY 4.0"},{uri:"https://creativecommons.org/licenses/by-sa/4.0/",shortName:"CC BY-SA 4.0"},{uri:"https://creativecommons.org/licenses/by-nd/4.0/",shortName:"CC BY-ND 4.0"},{uri:"https://creativecommons.org/licenses/by-nc/4.0/",shortName:"CC BY-NC 4.0"},{uri:"https://creativecommons.org/licenses/by-nc-sa/4.0/",shortName:"CC BY-NC-SA 4.0"},{uri:"https://creativecommons.org/licenses/by-nc-nd/4.0/",shortName:"CC BY-NC-ND 4.0"},{uri:"https://creativecommons.org/licenses/by/3.0/",shortName:"CC BY 3.0"},{uri:"https://creativecommons.org/licenses/by-sa/3.0/",shortName:"CC BY-SA 3.0"},{uri:"https://creativecommons.org/licenses/by-nd/3.0/",shortName:"CC BY-ND 3.0"},{uri:"https://creativecommons.org/licenses/by-nc/3.0/",shortName:"CC BY-NC 3.0"},{uri:"https://creativecommons.org/licenses/by-nc-sa/3.0/",shortName:"CC BY-NC-SA 3.0"},{uri:"https://creativecommons.org/licenses/by-nc-nd/3.0/",shortName:"CC BY-NC-ND 3.0"}];function Et(i){const e=We.find(t=>t.uri===i);return e?e.shortName:null}const At=[{code:"en",label:"English"},{code:"de",label:"Deutsch"},{code:"fr",label:"Français"},{code:"it",label:"Italiano"},{code:"es",label:"Español"},{code:"pt",label:"Português"}],Tt=[{value:"image",label:"Image"},{value:"video",label:"Video"},{value:"audio",label:"Audio"},{value:"text",label:"Text"},{value:"application/pdf",label:"PDF"}];function ee(i,e){return!i||i.length<=e?i:i.slice(0,e-3)+"..."}function Ye(i){return ee(i,40)}function Ve(i){return ee(i,60)}function Ke(i){return ee(i,20)}function Je(i){return i.slice(0,4).map(e=>{const t=typeof e=="string"?e:String(e);return Ke(t)})}const Pt=K` + :host { + display: block; + width: 100%; + box-sizing: border-box; + } + + .card { + border: 1px solid var(--border-color, rgba(0, 0, 0, 0.1)); + border-radius: 8px; + overflow: hidden; + background: var(--background-card); + box-shadow: 0 2px 4px var(--shadow-color, rgba(0, 0, 0, 0.05)); + transition: + box-shadow 0.3s ease, + transform 0.3s ease; + display: flex; + flex-direction: column; + height: 100%; + } + + .card:hover { + box-shadow: 0 8px 16px var(--shadow-color-hover, rgba(0, 0, 0, 0.15)); + transform: translateY(-2px); + } + + .thumbnail-container { + width: 100%; + aspect-ratio: 16 / 9; + overflow: hidden; + background: var(--background-muted, #f5f5f5); + position: relative; + cursor: pointer; + } + + .thumbnail { + width: 100%; + height: 100%; + object-fit: cover; + transition: transform 0.2s ease; + } + + .thumbnail-container:hover .thumbnail { + transform: scale(1.05); + } + + .placeholder { + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + background: linear-gradient(135deg, var(--primary-color) 0%, var(--secondary-color) 100%); + color: white; + font-size: 48px; + } + + .content { + padding: 16px; + flex: 1; + display: flex; + flex-direction: column; + } + + .title { + font-size: 16px; + font-weight: 600; + margin: 0 0 8px 0; + color: var(--text-primary); + line-height: 1.4; + overflow: hidden; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + } + + .title a { + color: var(--text-primary); + text-decoration: none; + } + + .title a:hover { + color: var(--primary-color); + text-decoration: underline; + } + + .description { + font-size: 14px; + color: var(--text-secondary); + margin: 0 0 12px 0; + line-height: 1.5; + overflow: hidden; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + flex: 1; + } + + .metadata { + display: flex; + flex-direction: column; + gap: 8px; + margin-top: auto; + } + + .license { + font-size: 12px; + color: var(--text-secondary); + } + + .license a { + color: var(--primary-color); + text-decoration: none; + font-weight: 500; + } + + .license a:hover { + text-decoration: underline; + } + + .keywords { + display: flex; + flex-wrap: wrap; + gap: 6px; + } + + .keyword { + background: var(--button-secondary-bg, rgba(0, 0, 0, 0.05)); + padding: 4px 8px; + border-radius: 4px; + font-size: 11px; + color: var(--text-secondary); + } + + .attribution { + font-size: 10px; + color: var(--text-muted); + line-height: 1.4; + margin-top: 4px; + padding-top: 8px; + border-top: 1px solid var(--border-color-subtle, rgba(0, 0, 0, 0.05)); + } + + .no-data { + color: var(--text-muted); + font-style: italic; + font-size: 12px; + } +`;var Ct=Object.defineProperty,Ot=Object.getOwnPropertyDescriptor,me=(i,e,t,s)=>{for(var r=s>1?void 0:s?Ot(e,t):e,n=i.length-1,a;n>=0;n--)(a=i[n])&&(r=(s?a(e,t,r):a(r))||r);return s&&r&&Ct(e,t,r),r};l.OerCardElement=class extends A{constructor(){super(...arguments),this.oer=null,this.language="en"}get t(){return De(this.language)}handleImageClick(){this.oer&&this.dispatchEvent(new CustomEvent("card-click",{detail:{oer:this.oer},bubbles:!0,composed:!0}))}getLicenseName(e){if(!e)return"Unknown License";const t=typeof e=="string"?e:JSON.stringify(e),s=Et(t);return s||(t.includes("creativecommons.org")?"Creative Commons":"License")}render(){var c,h,f,w,ye;if(!this.oer)return g` +
+
+

${this.t.noDataMessage}

+
+
+ `;const e=((c=this.oer.images)==null?void 0:c.small)??this.oer.url??null,t=Ye(this.oer.name||((h=this.oer.amb_metadata)==null?void 0:h.name)||this.t.untitledMessage),s=((f=this.oer.amb_metadata)==null?void 0:f.description)||this.oer.description,r=typeof s=="string"?s:"",n=r?Ve(r):"",a=this.oer.keywords||((w=this.oer.amb_metadata)==null?void 0:w.keywords)||[],o=Je(a),d=this.oer.license_uri||((ye=this.oer.amb_metadata)==null?void 0:ye.license),p=this.oer.attribution,u=this.oer.foreign_landing_url;return g` +
+
+ ${e?g`${this.oer.file_alt||t}`:g`
📚
`} +
+
+

+ ${u?g`${t}`:t} +

+ ${n?g`

${n}

`:""} + +
+
+ `}},l.OerCardElement.styles=Pt,me([b({type:Object})],l.OerCardElement.prototype,"oer",2),me([b({type:String})],l.OerCardElement.prototype,"language",2),l.OerCardElement=me([Q("oer-card")],l.OerCardElement);const kt=K` + :host { + display: block; + width: 100%; + box-sizing: border-box; + } + + .list-container { + width: 100%; + margin-bottom: 24px; + } + + .grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); + gap: 18px; + width: 100%; + } + + .empty-state { + text-align: center; + padding: 48px 24px; + color: var(--text-secondary); + } + + .empty-icon { + font-size: 64px; + margin-bottom: 16px; + } + + .empty-title { + font-size: 20px; + font-weight: 600; + margin: 0 0 8px 0; + color: var(--text-primary); + } + + .empty-message { + font-size: 14px; + margin: 0; + color: var(--text-secondary); + } + + .loading { + text-align: center; + padding: 48px 24px; + color: var(--text-secondary); + } + + .loading-spinner { + display: inline-block; + width: 40px; + height: 40px; + border: 4px solid var(--spinner-track-color, #f3f3f3); + border-top: 4px solid var(--primary-color); + border-radius: 50%; + animation: spin 1s linear infinite; + margin-bottom: 16px; + } + + @keyframes spin { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } + } + + .error { + text-align: center; + padding: 48px 24px; + color: var(--error-color, #d32f2f); + } + + .error-icon { + font-size: 48px; + margin-bottom: 16px; + } + + .error-message { + font-size: 14px; + margin: 0; + } +`;var zt=Object.defineProperty,Rt=Object.getOwnPropertyDescriptor,Y=(i,e,t,s)=>{for(var r=s>1?void 0:s?Rt(e,t):e,n=i.length-1,a;n>=0;n--)(a=i[n])&&(r=(s?a(e,t,r):a(r))||r);return s&&r&&zt(e,t,r),r};l.OerListElement=class extends A{constructor(){super(...arguments),this.oers=[],this.loading=!1,this.error=null,this.language="en"}get t(){return Ie(this.language)}render(){return this.loading?g` +
+
+

${this.t.loadingMessage}

+
+ `:this.error?g` +
+
⚠️
+

${this.error}

+
+ `:!this.oers||this.oers.length===0?g` +
+
📭
+

${this.t.emptyTitle}

+

${this.t.emptyMessage}

+
+ `:g` +
+
+ ${this.oers.map(e=>g` `)} +
+
+ `}},l.OerListElement.styles=kt,Y([b({type:Array})],l.OerListElement.prototype,"oers",2),Y([b({type:Boolean})],l.OerListElement.prototype,"loading",2),Y([b({type:String})],l.OerListElement.prototype,"error",2),Y([b({type:String})],l.OerListElement.prototype,"language",2),l.OerListElement=Y([Q("oer-list")],l.OerListElement);const Lt=/\{[^{}]+\}/g,Nt=()=>{var i,e;return typeof process=="object"&&Number.parseInt((e=(i=process==null?void 0:process.versions)==null?void 0:i.node)==null?void 0:e.substring(0,2))>=18&&process.versions.undici};function Ut(){return Math.random().toString(36).slice(2,11)}function jt(i){let{baseUrl:e="",Request:t=globalThis.Request,fetch:s=globalThis.fetch,querySerializer:r,bodySerializer:n,headers:a,requestInitExt:o=void 0,...d}={...i};o=Nt()?o:void 0,e=et(e);const p=[];async function u(c,h){const{baseUrl:f,fetch:w=s,Request:ye=t,headers:se,params:U={},parseAs:ve="json",querySerializer:ie,bodySerializer:rt=n??Bt,body:st,...xe}=h||{};let $e=e;f&&($e=et(f)??e);let we=typeof r=="function"?r:Qe(r);ie&&(we=typeof ie=="function"?ie:Qe({...typeof r=="object"?r:{},...ie}));const _e=st===void 0?void 0:rt(st,Xe(a,se,U.header)),Kt=Xe(_e===void 0||_e instanceof FormData?{}:{"Content-Type":"application/json"},a,se,U.header),Jt={redirect:"follow",...d,...xe,body:_e,headers:Kt};let ne,ae,T=new t(Ht(c,{baseUrl:$e,params:U,querySerializer:we}),Jt),y;for(const $ in xe)$ in T||(T[$]=xe[$]);if(p.length){ne=Ut(),ae=Object.freeze({baseUrl:$e,fetch:w,parseAs:ve,querySerializer:we,bodySerializer:rt});for(const $ of p)if($&&typeof $=="object"&&typeof $.onRequest=="function"){const v=await $.onRequest({request:T,schemaPath:c,params:U,options:ae,id:ne});if(v)if(v instanceof t)T=v;else if(v instanceof Response){y=v;break}else throw new Error("onRequest: must return new Request() or Response() when modifying the request")}}if(!y){try{y=await w(T,o)}catch($){let v=$;if(p.length)for(let z=p.length-1;z>=0;z--){const oe=p[z];if(oe&&typeof oe=="object"&&typeof oe.onError=="function"){const V=await oe.onError({request:T,error:v,schemaPath:c,params:U,options:ae,id:ne});if(V){if(V instanceof Response){v=void 0,y=V;break}if(V instanceof Error){v=V;continue}throw new Error("onError: must return new Response() or instance of Error")}}}if(v)throw v}if(p.length)for(let $=p.length-1;$>=0;$--){const v=p[$];if(v&&typeof v=="object"&&typeof v.onResponse=="function"){const z=await v.onResponse({request:T,response:y,schemaPath:c,params:U,options:ae,id:ne});if(z){if(!(z instanceof Response))throw new Error("onResponse: must return new Response() when modifying the response");y=z}}}}if(y.status===204||T.method==="HEAD"||y.headers.get("Content-Length")==="0")return y.ok?{data:void 0,response:y}:{error:void 0,response:y};if(y.ok)return ve==="stream"?{data:y.body,response:y}:{data:await y[ve](),response:y};let Se=await y.text();try{Se=JSON.parse(Se)}catch{}return{error:Se,response:y}}return{request(c,h,f){return u(h,{...f,method:c.toUpperCase()})},GET(c,h){return u(c,{...h,method:"GET"})},PUT(c,h){return u(c,{...h,method:"PUT"})},POST(c,h){return u(c,{...h,method:"POST"})},DELETE(c,h){return u(c,{...h,method:"DELETE"})},OPTIONS(c,h){return u(c,{...h,method:"OPTIONS"})},HEAD(c,h){return u(c,{...h,method:"HEAD"})},PATCH(c,h){return u(c,{...h,method:"PATCH"})},TRACE(c,h){return u(c,{...h,method:"TRACE"})},use(...c){for(const h of c)if(h){if(typeof h!="object"||!("onRequest"in h||"onResponse"in h||"onError"in h))throw new Error("Middleware must be an object with one of `onRequest()`, `onResponse() or `onError()`");p.push(h)}},eject(...c){for(const h of c){const f=p.indexOf(h);f!==-1&&p.splice(f,1)}}}}function te(i,e,t){if(e==null)return"";if(typeof e=="object")throw new Error("Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.");return`${i}=${(t==null?void 0:t.allowReserved)===!0?e:encodeURIComponent(e)}`}function Ge(i,e,t){if(!e||typeof e!="object")return"";const s=[],r={simple:",",label:".",matrix:";"}[t.style]||"&";if(t.style!=="deepObject"&&t.explode===!1){for(const o in e)s.push(o,t.allowReserved===!0?e[o]:encodeURIComponent(e[o]));const a=s.join(",");switch(t.style){case"form":return`${i}=${a}`;case"label":return`.${a}`;case"matrix":return`;${i}=${a}`;default:return a}}for(const a in e){const o=t.style==="deepObject"?`${i}[${a}]`:a;s.push(te(o,e[a],t))}const n=s.join(r);return t.style==="label"||t.style==="matrix"?`${r}${n}`:n}function Ze(i,e,t){if(!Array.isArray(e))return"";if(t.explode===!1){const n={form:",",spaceDelimited:"%20",pipeDelimited:"|"}[t.style]||",",a=(t.allowReserved===!0?e:e.map(o=>encodeURIComponent(o))).join(n);switch(t.style){case"simple":return a;case"label":return`.${a}`;case"matrix":return`;${i}=${a}`;default:return`${i}=${a}`}}const s={simple:",",label:".",matrix:";"}[t.style]||"&",r=[];for(const n of e)t.style==="simple"||t.style==="label"?r.push(t.allowReserved===!0?n:encodeURIComponent(n)):r.push(te(i,n,t));return t.style==="label"||t.style==="matrix"?`${s}${r.join(s)}`:r.join(s)}function Qe(i){return function(t){const s=[];if(t&&typeof t=="object")for(const r in t){const n=t[r];if(n!=null){if(Array.isArray(n)){if(n.length===0)continue;s.push(Ze(r,n,{style:"form",explode:!0,...i==null?void 0:i.array,allowReserved:(i==null?void 0:i.allowReserved)||!1}));continue}if(typeof n=="object"){s.push(Ge(r,n,{style:"deepObject",explode:!0,...i==null?void 0:i.object,allowReserved:(i==null?void 0:i.allowReserved)||!1}));continue}s.push(te(r,n,i))}}return s.join("&")}}function Mt(i,e){let t=i;for(const s of i.match(Lt)??[]){let r=s.substring(1,s.length-1),n=!1,a="simple";if(r.endsWith("*")&&(n=!0,r=r.substring(0,r.length-1)),r.startsWith(".")?(a="label",r=r.substring(1)):r.startsWith(";")&&(a="matrix",r=r.substring(1)),!e||e[r]===void 0||e[r]===null)continue;const o=e[r];if(Array.isArray(o)){t=t.replace(s,Ze(r,o,{style:a,explode:n}));continue}if(typeof o=="object"){t=t.replace(s,Ge(r,o,{style:a,explode:n}));continue}if(a==="matrix"){t=t.replace(s,`;${te(r,o)}`);continue}t=t.replace(s,a==="label"?`.${encodeURIComponent(o)}`:encodeURIComponent(o))}return t}function Bt(i,e){return i instanceof FormData?i:e&&(e.get instanceof Function?e.get("Content-Type")??e.get("content-type"):e["Content-Type"]??e["content-type"])==="application/x-www-form-urlencoded"?new URLSearchParams(i).toString():JSON.stringify(i)}function Ht(i,e){var r;let t=`${e.baseUrl}${i}`;(r=e.params)!=null&&r.path&&(t=Mt(t,e.params.path));let s=e.querySerializer(e.params.query??{});return s.startsWith("?")&&(s=s.substring(1)),s&&(t+=`?${s}`),t}function Xe(...i){const e=new Headers;for(const t of i){if(!t||typeof t!="object")continue;const s=t instanceof Headers?t.entries():Object.entries(t);for(const[r,n]of s)if(n===null)e.delete(r);else if(Array.isArray(n))for(const a of n)e.append(r,a);else n!==void 0&&e.set(r,n)}return e}function et(i){return i.endsWith("/")?i.substring(0,i.length-1):i}function be(i,e){return jt({baseUrl:i.replace(/\/$/,""),headers:e==null?void 0:e.headers,fetch:e==null?void 0:e.fetch})}const Dt=K` + :host { + display: block; + width: 100%; + box-sizing: border-box; + } + + .search-wrapper { + display: flex; + flex-direction: column; + gap: 0; + } + + .slot-container { + margin-top: 24px; + } + + .slot-container:empty { + display: none; + margin-top: 0; + } + + .search-container { + background: var(--background-form); + border: 1px solid var(--border-color, rgba(0, 0, 0, 0.1)); + border-radius: 8px; + padding: 24px; + margin-bottom: 24px; + } + + .search-header { + margin: 0 0 16px 0; + font-size: 20px; + font-weight: 600; + color: var(--text-primary); + } + + .search-form { + display: flex; + flex-direction: column; + gap: 16px; + } + + .form-row { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: 12px; + } + + .form-group { + display: flex; + flex-direction: column; + gap: 6px; + } + + label { + font-size: 13px; + font-weight: 500; + color: var(--text-secondary); + } + + input, + select { + width: 100%; + padding: 10px 12px; + border: 1px solid var(--input-border-color, rgba(0, 0, 0, 0.15)); + border-radius: 6px; + font-size: 14px; + font-family: inherit; + transition: border-color 0.2s ease; + box-sizing: border-box; + background: var(--background-input, white); + color: var(--text-primary); + } + + input:focus, + select:focus { + outline: none; + border-color: var(--primary-color); + } + + .button-group { + display: flex; + gap: 12px; + margin-top: 8px; + } + + button { + padding: 10px 20px; + border: none; + border-radius: 6px; + font-size: 14px; + font-weight: 500; + cursor: pointer; + transition: all 0.2s ease; + font-family: inherit; + } + + .search-button { + background: var(--primary-color); + color: white; + flex: 1; + } + + .search-button:hover:not(:disabled) { + background: var(--primary-hover-color); + } + + .search-button:disabled { + background: #ccc; + cursor: not-allowed; + } + + .clear-button { + background: var(--button-secondary-bg, rgba(0, 0, 0, 0.05)); + color: var(--text-secondary); + flex: 0 0 auto; + } + + .clear-button:hover { + background: var(--button-secondary-hover-bg, rgba(0, 0, 0, 0.1)); + } + + .pagination { + display: flex; + justify-content: space-between; + align-items: center; + padding: 16px; + background: var(--background-form); + border: 1px solid var(--border-color, rgba(0, 0, 0, 0.1)); + border-radius: 8px; + margin-top: 24px; + gap: 12px; + flex-wrap: wrap; + } + + .pagination-info { + font-size: 14px; + color: var(--text-secondary); + flex: 1 1 100%; + text-align: center; + margin-bottom: 8px; + } + + .pagination-controls { + display: flex; + gap: 8px; + align-items: center; + flex-wrap: wrap; + justify-content: center; + flex: 1 1 100%; + } + + .page-button { + padding: 8px 12px; + background: var(--button-secondary-bg, rgba(0, 0, 0, 0.05)); + color: var(--text-primary); + min-width: 40px; + flex-shrink: 0; + } + + .page-button:hover:not(:disabled) { + background: var(--button-secondary-hover-bg, rgba(0, 0, 0, 0.1)); + } + + .page-button:disabled { + background: var(--button-secondary-bg, rgba(0, 0, 0, 0.05)); + color: var(--text-disabled, rgba(0, 0, 0, 0.3)); + cursor: not-allowed; + } + + .page-info { + font-size: 14px; + color: var(--text-secondary); + margin: 0 8px; + white-space: nowrap; + } + + /* Mobile responsive styles */ + @media (max-width: 768px) { + .search-container { + padding: 16px; + } + + .pagination { + padding: 12px; + flex-direction: column; + } + + .pagination-info { + margin-bottom: 12px; + font-size: 13px; + } + + .pagination-controls { + gap: 6px; + width: 100%; + } + + .page-button { + padding: 8px 10px; + font-size: 13px; + min-width: 60px; + flex: 1 1 auto; + } + + .page-info { + flex-basis: 100%; + text-align: center; + margin: 8px 0; + font-size: 13px; + } + + .button-group { + flex-direction: column; + } + + .search-button, + .clear-button { + width: 100%; + } + } + + @media (max-width: 480px) { + .search-container { + padding: 12px; + } + + .pagination { + padding: 10px; + } + + .pagination-info { + font-size: 12px; + } + + .pagination-controls { + gap: 4px; + } + + .page-button { + padding: 6px 8px; + font-size: 12px; + min-width: 50px; + } + + .page-info { + font-size: 12px; + margin: 6px 0; + } + + .form-row { + grid-template-columns: 1fr; + } + } + + .error-message { + background: #ffebee; + color: #c62828; + padding: 12px 16px; + border-radius: 6px; + margin-top: 12px; + font-size: 14px; + } + + .toggle-filters-button { + background: transparent; + color: var(--primary-color); + padding: 8px 0; + font-size: 14px; + font-weight: 500; + border: none; + cursor: pointer; + text-align: left; + display: flex; + align-items: center; + gap: 6px; + margin-bottom: 12px; + } + + .toggle-filters-button::before { + content: '▶'; + display: inline-block; + transition: transform 0.2s ease; + font-size: 10px; + } + + .toggle-filters-button:hover { + color: var(--primary-hover-color); + } + + .advanced-filters { + max-height: 0; + overflow: hidden; + transition: max-height 0.3s ease; + display: flex; + flex-direction: column; + gap: 16px; + } + + .advanced-filters.expanded { + max-height: 1000px; + } + + .advanced-filters.expanded ~ .toggle-filters-button::before, + .toggle-filters-button:has(~ .advanced-filters.expanded)::before { + transform: rotate(90deg); + } + + /* Fix the button state when filters are expanded */ + form:has(.advanced-filters.expanded) .toggle-filters-button::before { + transform: rotate(90deg); + } +`;var It=Object.defineProperty,Ft=Object.getOwnPropertyDescriptor,x=(i,e,t,s)=>{for(var r=s>1?void 0:s?Ft(e,t):e,n=i.length-1,a;n>=0;n--)(a=i[n])&&(r=(s?a(e,t,r):a(r))||r);return s&&r&&It(e,t,r),r};l.OerSearchElement=class extends A{constructor(){super(...arguments),this.apiUrl="http://localhost:3000",this.language="en",this.showTypeFilter=!0,this.pageSize=20,this.availableSources=[],this.showSourceFilter=!0,this.client=null,this.searchParams={page:1,source:X},this.loading=!1,this.error=null,this.advancedFiltersExpanded=!1,this.handleSlottedPageChange=e=>{const t=e;e.stopPropagation(),this.searchParams={...this.searchParams,page:t.detail.page},this.performSearch()}}get t(){return Fe(this.language)}connectedCallback(){super.connectedCallback(),this.client=be(this.apiUrl),this.searchParams={...this.searchParams,pageSize:this.pageSize},this.lockedType&&(this.searchParams={...this.searchParams,type:this.lockedType}),this.lockedSource&&(this.searchParams={...this.searchParams,source:this.lockedSource}),this.addEventListener("page-change",this.handleSlottedPageChange)}disconnectedCallback(){super.disconnectedCallback(),this.removeEventListener("page-change",this.handleSlottedPageChange)}updated(e){if(super.updated(e),e.has("apiUrl")&&(this.client=be(this.apiUrl)),e.has("pageSize")&&(this.searchParams={...this.searchParams,pageSize:this.pageSize}),e.has("lockedType"))if(this.lockedType)this.searchParams={...this.searchParams,type:this.lockedType};else{const{type:t,...s}=this.searchParams;this.searchParams=s}e.has("lockedSource")&&(this.lockedSource?this.searchParams={...this.searchParams,source:this.lockedSource}:this.searchParams={...this.searchParams,source:X})}async performSearch(){if(this.client){this.loading=!0,this.error=null;try{const e=await this.client.GET("/api/v1/oer",{params:{query:this.searchParams}});if(e.error){const t=e.error.message?Array.isArray(e.error.message)?e.error.message.join(", "):e.error.message:"Failed to fetch resources";throw new Error(t)}e.data&&this.dispatchEvent(new CustomEvent("search-results",{detail:{data:e.data.data,meta:e.data.meta},bubbles:!0,composed:!0}))}catch(e){this.error=e instanceof Error?e.message:this.t.errorMessage,this.dispatchEvent(new CustomEvent("search-error",{detail:{error:this.error},bubbles:!0,composed:!0}))}finally{this.loading=!1}}}handleSubmit(e){e.preventDefault(),this.searchParams={...this.searchParams,page:1},this.performSearch()}handleClear(){this.searchParams={page:1,pageSize:this.pageSize,source:this.lockedSource||X},this.lockedType&&(this.searchParams={...this.searchParams,type:this.lockedType}),this.error=null,this.dispatchEvent(new CustomEvent("search-cleared",{bubbles:!0,composed:!0}))}handleInputChange(e){return t=>{const r=t.target.value.trim();if(r===""){const{[e]:n,...a}=this.searchParams;this.searchParams=a}else this.searchParams={...this.searchParams,[e]:r}}}handleBooleanChange(e){return t=>{const r=t.target.value;if(r===""){const{[e]:n,...a}=this.searchParams;this.searchParams=a}else this.searchParams={...this.searchParams,[e]:r==="true"}}}toggleAdvancedFilters(){this.advancedFiltersExpanded=!this.advancedFiltersExpanded}render(){return g` +
+
+

${this.t.headerTitle}

+
+
+ + +
+ + ${this.showTypeFilter&&!this.lockedType?g` +
+ + +
+ `:""} + + + +
+
+
+ + +
+ +
+ + +
+
+ + ${this.showSourceFilter&&!this.lockedSource&&this.availableSources.length>0?g` +
+ + +
+ `:""} +
+ +
+ + +
+ + ${this.error?g`
${this.error}
`:""} +
+
+
+ +
+
+ `}},l.OerSearchElement.styles=Dt,x([b({type:String,attribute:"api-url"})],l.OerSearchElement.prototype,"apiUrl",2),x([b({type:String})],l.OerSearchElement.prototype,"language",2),x([b({type:String,attribute:"locked-type"})],l.OerSearchElement.prototype,"lockedType",2),x([b({type:Boolean,attribute:"show-type-filter"})],l.OerSearchElement.prototype,"showTypeFilter",2),x([b({type:Number,attribute:"page-size"})],l.OerSearchElement.prototype,"pageSize",2),x([b({type:Array,attribute:"available-sources"})],l.OerSearchElement.prototype,"availableSources",2),x([b({type:String,attribute:"locked-source"})],l.OerSearchElement.prototype,"lockedSource",2),x([b({type:Boolean,attribute:"show-source-filter"})],l.OerSearchElement.prototype,"showSourceFilter",2),x([q()],l.OerSearchElement.prototype,"client",2),x([q()],l.OerSearchElement.prototype,"searchParams",2),x([q()],l.OerSearchElement.prototype,"loading",2),x([q()],l.OerSearchElement.prototype,"error",2),x([q()],l.OerSearchElement.prototype,"advancedFiltersExpanded",2),l.OerSearchElement=x([Q("oer-search")],l.OerSearchElement);const qt=K` + :host { + display: block; + width: 100%; + } + + .pagination { + display: flex; + justify-content: space-between; + align-items: center; + padding: 16px; + background: var(--background-form); + border: 1px solid var(--border-color, rgba(0, 0, 0, 0.1)); + border-radius: 8px; + gap: 12px; + flex-wrap: wrap; + } + + .pagination-info { + font-size: 14px; + color: var(--text-secondary); + flex: 1 1 100%; + text-align: center; + margin-bottom: 8px; + } + + .pagination-controls { + display: flex; + gap: 8px; + align-items: center; + flex-wrap: wrap; + justify-content: center; + flex: 1 1 100%; + } + + .page-button { + padding: 8px 12px; + background: var(--button-secondary-bg, rgba(0, 0, 0, 0.05)); + color: var(--text-primary); + min-width: 40px; + flex-shrink: 0; + border: none; + border-radius: 6px; + font-size: 14px; + font-weight: 500; + cursor: pointer; + transition: all 0.2s ease; + font-family: inherit; + } + + .page-button:hover:not(:disabled) { + background: var(--button-secondary-hover-bg, rgba(0, 0, 0, 0.1)); + } + + .page-button:disabled { + background: var(--button-secondary-bg, rgba(0, 0, 0, 0.05)); + color: var(--text-disabled, rgba(0, 0, 0, 0.3)); + cursor: not-allowed; + } + + .page-info { + font-size: 14px; + color: var(--text-secondary); + margin: 0 8px; + white-space: nowrap; + } + + /* Mobile responsive styles */ + @media (max-width: 768px) { + .pagination { + padding: 12px; + flex-direction: column; + } + + .pagination-info { + margin-bottom: 12px; + font-size: 13px; + } + + .pagination-controls { + gap: 6px; + width: 100%; + } + + .page-button { + padding: 8px 10px; + font-size: 13px; + min-width: 60px; + flex: 1 1 auto; + } + + .page-info { + flex-basis: 100%; + text-align: center; + margin: 8px 0; + font-size: 13px; + } + } + + @media (max-width: 480px) { + .pagination { + padding: 10px; + } + + .pagination-info { + font-size: 12px; + } + + .pagination-controls { + gap: 4px; + } + + .page-button { + padding: 6px 8px; + font-size: 12px; + min-width: 50px; + } + + .page-info { + font-size: 12px; + margin: 6px 0; + } + } +`;var Wt=Object.defineProperty,Yt=Object.getOwnPropertyDescriptor,re=(i,e,t,s)=>{for(var r=s>1?void 0:s?Yt(e,t):e,n=i.length-1,a;n>=0;n--)(a=i[n])&&(r=(s?a(e,t,r):a(r))||r);return s&&r&&Wt(e,t,r),r};l.PaginationElement=class extends A{constructor(){super(...arguments),this.metadata=null,this.loading=!1,this.language="en"}get t(){return qe(this.language)}render(){return this.metadata?g` + + `:""}handlePageChange(e){this.dispatchEvent(new CustomEvent("page-change",{detail:{page:e},bubbles:!0,composed:!0}))}},l.PaginationElement.styles=qt,re([b({type:Object})],l.PaginationElement.prototype,"metadata",2),re([b({type:Boolean})],l.PaginationElement.prototype,"loading",2),re([b({type:String})],l.PaginationElement.prototype,"language",2),l.PaginationElement=re([Q("oer-pagination")],l.PaginationElement);const Vt="0.0.1";l.VERSION=Vt,l.createOerClient=be,l.getCardTranslations=De,l.getListTranslations=Ie,l.getPaginationTranslations=qe,l.getSearchTranslations=Fe,l.getTranslations=W,l.shortenLabels=Je,l.truncateContent=Ve,l.truncateLabel=Ke,l.truncateText=ee,l.truncateTitle=Ye,Object.defineProperty(l,Symbol.toStringTag,{value:"Module"})})); diff --git a/packages/oer-finder-plugin/dist/oer-search/OerSearch.d.ts b/packages/oer-finder-plugin/dist/oer-search/OerSearch.d.ts new file mode 100644 index 0000000..0b2544d --- /dev/null +++ b/packages/oer-finder-plugin/dist/oer-search/OerSearch.d.ts @@ -0,0 +1,57 @@ +import { LitElement } from 'lit'; +import type { components } from '@edufeed-org/oer-finder-api-client'; +import { type SupportedLanguage } from '../translations.js'; +type OerItem = components['schemas']['OerItemSchema']; +export interface SearchParams { + page?: number; + pageSize?: number; + source?: string; + type?: string; + searchTerm?: string; + license?: string; + free_for_use?: boolean; + educational_level?: string; + language?: string; +} +export interface SourceOption { + value: string; + label: string; +} +export interface OerSearchResultEvent { + data: OerItem[]; + meta: components['schemas']['OerMetadataSchema']; +} +export declare class OerSearchElement extends LitElement { + static styles: import("lit").CSSResult; + apiUrl: string; + language: SupportedLanguage; + lockedType?: string; + showTypeFilter: boolean; + pageSize: number; + availableSources: SourceOption[]; + lockedSource?: string; + showSourceFilter: boolean; + private get t(); + private client; + private searchParams; + private loading; + private error; + private advancedFiltersExpanded; + connectedCallback(): void; + disconnectedCallback(): void; + private handleSlottedPageChange; + updated(changedProperties: Map): void; + private performSearch; + private handleSubmit; + private handleClear; + private handleInputChange; + private handleBooleanChange; + private toggleAdvancedFilters; + render(): import("lit").TemplateResult<1>; +} +declare global { + interface HTMLElementTagNameMap { + 'oer-search': OerSearchElement; + } +} +export {}; diff --git a/packages/oer-finder-plugin/dist/oer-search/OerSearch.test.d.ts b/packages/oer-finder-plugin/dist/oer-search/OerSearch.test.d.ts new file mode 100644 index 0000000..ca667db --- /dev/null +++ b/packages/oer-finder-plugin/dist/oer-search/OerSearch.test.d.ts @@ -0,0 +1 @@ +import './OerSearch.js'; diff --git a/packages/oer-finder-plugin/dist/oer-search/styles.d.ts b/packages/oer-finder-plugin/dist/oer-search/styles.d.ts new file mode 100644 index 0000000..1c75ade --- /dev/null +++ b/packages/oer-finder-plugin/dist/oer-search/styles.d.ts @@ -0,0 +1 @@ +export declare const styles: import("lit").CSSResult; diff --git a/packages/oer-finder-plugin/dist/pagination/Pagination.d.ts b/packages/oer-finder-plugin/dist/pagination/Pagination.d.ts new file mode 100644 index 0000000..49b21ef --- /dev/null +++ b/packages/oer-finder-plugin/dist/pagination/Pagination.d.ts @@ -0,0 +1,20 @@ +import { LitElement } from 'lit'; +import type { components } from '@edufeed-org/oer-finder-api-client'; +import { type SupportedLanguage } from '../translations.js'; +export interface OerPageChangeEvent { + page: number; +} +export declare class PaginationElement extends LitElement { + static styles: import("lit").CSSResult; + metadata: components['schemas']['OerMetadataSchema'] | null; + loading: boolean; + language: SupportedLanguage; + private get t(); + render(): import("lit").TemplateResult<1> | ""; + private handlePageChange; +} +declare global { + interface HTMLElementTagNameMap { + 'oer-pagination': PaginationElement; + } +} diff --git a/packages/oer-finder-plugin/dist/pagination/Pagination.test.d.ts b/packages/oer-finder-plugin/dist/pagination/Pagination.test.d.ts new file mode 100644 index 0000000..ad92854 --- /dev/null +++ b/packages/oer-finder-plugin/dist/pagination/Pagination.test.d.ts @@ -0,0 +1 @@ +import './Pagination.js'; diff --git a/packages/oer-finder-plugin/dist/pagination/styles.d.ts b/packages/oer-finder-plugin/dist/pagination/styles.d.ts new file mode 100644 index 0000000..1c75ade --- /dev/null +++ b/packages/oer-finder-plugin/dist/pagination/styles.d.ts @@ -0,0 +1 @@ +export declare const styles: import("lit").CSSResult; diff --git a/packages/oer-finder-plugin/dist/translations.d.ts b/packages/oer-finder-plugin/dist/translations.d.ts new file mode 100644 index 0000000..197a72e --- /dev/null +++ b/packages/oer-finder-plugin/dist/translations.d.ts @@ -0,0 +1,66 @@ +/** + * Translation system for OER Finder Plugin + * Supports English (default) and German + */ +export type SupportedLanguage = 'en' | 'de'; +export interface OerCardTranslations { + noDataMessage: string; + untitledMessage: string; + licenseLabel: string; + noLicenseMessage: string; +} +export interface PaginationTranslations { + firstButtonText: string; + previousButtonText: string; + nextButtonText: string; + lastButtonText: string; + showingPagesText: string; + totalResourcesText: string; + pageOfText: string; + ofText: string; +} +export interface OerListTranslations { + loadingMessage: string; + emptyTitle: string; + emptyMessage: string; +} +export interface OerSearchTranslations { + headerTitle: string; + keywordsLabel: string; + languageLabel: string; + licenseLabel: string; + freeForUseLabel: string; + sourceLabel: string; + typeLabel: string; + keywordsPlaceholder: string; + languagePlaceholder: string; + licensePlaceholder: string; + typePlaceholder: string; + searchingText: string; + searchButtonText: string; + clearButtonText: string; + anyOptionText: string; + yesOptionText: string; + noOptionText: string; + firstButtonText: string; + previousButtonText: string; + nextButtonText: string; + lastButtonText: string; + showingPagesText: string; + totalResourcesText: string; + pageOfText: string; + advancedFiltersShowText: string; + advancedFiltersHideText: string; + errorMessage: string; +} +export interface Translations { + card: OerCardTranslations; + list: OerListTranslations; + search: OerSearchTranslations; + pagination: PaginationTranslations; +} +export declare function getTranslations(language: SupportedLanguage): Translations; +export declare function getCardTranslations(language: SupportedLanguage): OerCardTranslations; +export declare function getListTranslations(language: SupportedLanguage): OerListTranslations; +export declare function getSearchTranslations(language: SupportedLanguage): OerSearchTranslations; +export declare function getPaginationTranslations(language: SupportedLanguage): PaginationTranslations; diff --git a/packages/oer-finder-plugin/dist/utils.d.ts b/packages/oer-finder-plugin/dist/utils.d.ts new file mode 100644 index 0000000..25634ca --- /dev/null +++ b/packages/oer-finder-plugin/dist/utils.d.ts @@ -0,0 +1,34 @@ +/** + * Text truncation utilities for OER content display + */ +/** + * Truncates a string to a maximum length and adds ellipsis if needed + * @param text - The text to truncate + * @param maxLength - Maximum length of the text + * @returns Truncated text with ellipsis if needed + */ +export declare function truncateText(text: string, maxLength: number): string; +/** + * Truncates title text to 50 characters maximum + * @param title - The title to truncate + * @returns Truncated title + */ +export declare function truncateTitle(title: string): string; +/** + * Truncates description/content text to 100 characters maximum + * @param content - The content to truncate + * @returns Truncated content + */ +export declare function truncateContent(content: string): string; +/** + * Truncates label text to 20 characters maximum + * @param label - The label to truncate + * @returns Truncated label + */ +export declare function truncateLabel(label: string): string; +/** + * Processes an array of labels, truncating each to 20 chars and limiting to 4 labels + * @param labels - Array of labels to process + * @returns Processed array with max 4 labels, each truncated to 20 chars + */ +export declare function shortenLabels(labels: (string | Record)[]): string[]; diff --git a/packages/oer-finder-plugin/dist/utils.test.d.ts b/packages/oer-finder-plugin/dist/utils.test.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/packages/oer-finder-plugin/dist/utils.test.d.ts @@ -0,0 +1 @@ +export {};