mirror of
https://github.com/usetrmnl/trmnl-picker.git
synced 2026-04-29 13:44:02 -07:00
Rebuild
This commit is contained in:
Vendored
+87
-7
@@ -1,9 +1,56 @@
|
||||
// src/index.js
|
||||
var _DEFAULT_MODEL_NAME = "og_plus";
|
||||
var _API_CACHE_KEY = "trmnl-picker-api-cache";
|
||||
var _CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
||||
var TRMNLPicker = class _TRMNLPicker {
|
||||
static API_BASE_URL = "https://usetrmnl.com";
|
||||
/**
|
||||
* Get cached API response from localStorage
|
||||
* @private
|
||||
* @static
|
||||
* @returns {{models: Array, palettes: Array} | null} Cached data or null if expired/missing
|
||||
*/
|
||||
static _getCachedApiData() {
|
||||
try {
|
||||
const cached = localStorage.getItem(_API_CACHE_KEY);
|
||||
if (!cached)
|
||||
return null;
|
||||
const { timestamp, models, palettes } = JSON.parse(cached);
|
||||
const now = Date.now();
|
||||
if (now - timestamp > _CACHE_TTL_MS) {
|
||||
localStorage.removeItem(_API_CACHE_KEY);
|
||||
return null;
|
||||
}
|
||||
return { models, palettes };
|
||||
} catch (error) {
|
||||
console.warn("TRMNLPicker: Failed to read API cache:", error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Save API response to localStorage cache
|
||||
* @private
|
||||
* @static
|
||||
* @param {Array} models - Models array
|
||||
* @param {Array} palettes - Palettes array
|
||||
*/
|
||||
static _setCachedApiData(models, palettes) {
|
||||
try {
|
||||
const cacheData = {
|
||||
timestamp: Date.now(),
|
||||
models,
|
||||
palettes
|
||||
};
|
||||
localStorage.setItem(_API_CACHE_KEY, JSON.stringify(cacheData));
|
||||
} catch (error) {
|
||||
console.warn("TRMNLPicker: Failed to save API cache:", error);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Create a TRMNLPicker instance, fetching data from TRMNL API if not provided
|
||||
*
|
||||
* Automatically caches API responses in localStorage for 24 hours to reduce network requests.
|
||||
*
|
||||
* @static
|
||||
* @param {string|Element} formIdOrElement - Form element ID or DOM element
|
||||
* @param {Object} options - Configuration options
|
||||
@@ -14,7 +61,7 @@ var TRMNLPicker = class _TRMNLPicker {
|
||||
* @throws {Error} If API fetch fails when models or palettes are not provided
|
||||
*
|
||||
* @example
|
||||
* // Fetch models and palettes from API
|
||||
* // Fetch models and palettes from API (or use cached data if available)
|
||||
* const picker = await TRMNLPicker.create('screen-picker')
|
||||
*
|
||||
* // Provide your own data
|
||||
@@ -22,6 +69,13 @@ var TRMNLPicker = class _TRMNLPicker {
|
||||
*/
|
||||
static async create(formId, options = {}) {
|
||||
let { models, palettes, localStorageKey } = options;
|
||||
if (!models && !palettes) {
|
||||
const cached = _TRMNLPicker._getCachedApiData();
|
||||
if (cached) {
|
||||
models = cached.models;
|
||||
palettes = cached.palettes;
|
||||
}
|
||||
}
|
||||
if (!models) {
|
||||
try {
|
||||
const response = await fetch(`${_TRMNLPicker.API_BASE_URL}/api/models`);
|
||||
@@ -46,6 +100,9 @@ var TRMNLPicker = class _TRMNLPicker {
|
||||
throw new Error(`TRMNLPicker: Failed to fetch palettes from API: ${error.message}`);
|
||||
}
|
||||
}
|
||||
if (!options.models && !options.palettes) {
|
||||
_TRMNLPicker._setCachedApiData(models, palettes);
|
||||
}
|
||||
return new _TRMNLPicker(formId, { models, palettes, localStorageKey });
|
||||
}
|
||||
constructor(formIdOrElement, options = {}) {
|
||||
@@ -245,7 +302,6 @@ var TRMNLPicker = class _TRMNLPicker {
|
||||
const event = new CustomEvent("trmnl:change", {
|
||||
detail: {
|
||||
origin,
|
||||
screenClasses: this.screenClasses,
|
||||
...this.state
|
||||
},
|
||||
bubbles: true
|
||||
@@ -353,7 +409,7 @@ var TRMNLPicker = class _TRMNLPicker {
|
||||
}
|
||||
/**
|
||||
* Get CSS classes for the current picker configuration
|
||||
* @public
|
||||
* @private
|
||||
* @returns {Array<string>} Array of CSS class names for Framework CSS rendering
|
||||
*
|
||||
* Generated classes (in order):
|
||||
@@ -369,7 +425,7 @@ var TRMNLPicker = class _TRMNLPicker {
|
||||
* const classes = picker.screenClasses
|
||||
* // ['screen', 'screen--1bit', 'screen--v2', 'screen--md', 'screen--1x']
|
||||
*/
|
||||
get screenClasses() {
|
||||
get _screenClasses() {
|
||||
const model = this._state.model;
|
||||
const palette = this._state.palette;
|
||||
if (!model) {
|
||||
@@ -507,7 +563,10 @@ var TRMNLPicker = class _TRMNLPicker {
|
||||
* model: Object,
|
||||
* palette: Object,
|
||||
* isPortrait: boolean,
|
||||
* isDarkMode: boolean
|
||||
* isDarkMode: boolean,
|
||||
* screenClasses: Array<string>,
|
||||
* width: number,
|
||||
* height: number
|
||||
* }} State object containing model (full model object from API), palette (full palette object from API), isPortrait flag, and isDarkMode flag
|
||||
*
|
||||
* @example
|
||||
@@ -516,11 +575,32 @@ var TRMNLPicker = class _TRMNLPicker {
|
||||
* // model: { name: 'og_plus', label: 'OG+', width: 800, height: 480, ... },
|
||||
* // palette: { id: '123', name: 'Black', framework_class: 'screen--1bit', ... },
|
||||
* // isPortrait: false,
|
||||
* // isDarkMode: false
|
||||
* // isDarkMode: false,
|
||||
* // screenClasses: ['screen', 'screen--1bit', 'screen--v2', 'screen--md', 'screen--1x'],
|
||||
* // width: 800,
|
||||
* // height: 480
|
||||
* // }
|
||||
*/
|
||||
get state() {
|
||||
return { ...this._state };
|
||||
return {
|
||||
screenClasses: this._screenClasses,
|
||||
...this._dimensions,
|
||||
...this._state
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Get current dimensions (width and height) of the screen in pixels
|
||||
* @private
|
||||
* @returns {{ width: number, height: number }} Object with width and height properties
|
||||
*/
|
||||
get _dimensions() {
|
||||
const model = this._state.model;
|
||||
let width = model.width / model.scale_factor;
|
||||
let height = model.height / model.scale_factor;
|
||||
if (this._state.isPortrait) {
|
||||
[width, height] = [height, width];
|
||||
}
|
||||
return { width, height };
|
||||
}
|
||||
/**
|
||||
* Clean up event listeners and references
|
||||
|
||||
Vendored
+2
-2
File diff suppressed because one or more lines are too long
Vendored
+87
-7
@@ -23,10 +23,57 @@ var TRMNLPicker = (() => {
|
||||
default: () => src_default
|
||||
});
|
||||
var _DEFAULT_MODEL_NAME = "og_plus";
|
||||
var _API_CACHE_KEY = "trmnl-picker-api-cache";
|
||||
var _CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
||||
var TRMNLPicker = class _TRMNLPicker {
|
||||
static API_BASE_URL = "https://usetrmnl.com";
|
||||
/**
|
||||
* Get cached API response from localStorage
|
||||
* @private
|
||||
* @static
|
||||
* @returns {{models: Array, palettes: Array} | null} Cached data or null if expired/missing
|
||||
*/
|
||||
static _getCachedApiData() {
|
||||
try {
|
||||
const cached = localStorage.getItem(_API_CACHE_KEY);
|
||||
if (!cached)
|
||||
return null;
|
||||
const { timestamp, models, palettes } = JSON.parse(cached);
|
||||
const now = Date.now();
|
||||
if (now - timestamp > _CACHE_TTL_MS) {
|
||||
localStorage.removeItem(_API_CACHE_KEY);
|
||||
return null;
|
||||
}
|
||||
return { models, palettes };
|
||||
} catch (error) {
|
||||
console.warn("TRMNLPicker: Failed to read API cache:", error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Save API response to localStorage cache
|
||||
* @private
|
||||
* @static
|
||||
* @param {Array} models - Models array
|
||||
* @param {Array} palettes - Palettes array
|
||||
*/
|
||||
static _setCachedApiData(models, palettes) {
|
||||
try {
|
||||
const cacheData = {
|
||||
timestamp: Date.now(),
|
||||
models,
|
||||
palettes
|
||||
};
|
||||
localStorage.setItem(_API_CACHE_KEY, JSON.stringify(cacheData));
|
||||
} catch (error) {
|
||||
console.warn("TRMNLPicker: Failed to save API cache:", error);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Create a TRMNLPicker instance, fetching data from TRMNL API if not provided
|
||||
*
|
||||
* Automatically caches API responses in localStorage for 24 hours to reduce network requests.
|
||||
*
|
||||
* @static
|
||||
* @param {string|Element} formIdOrElement - Form element ID or DOM element
|
||||
* @param {Object} options - Configuration options
|
||||
@@ -37,7 +84,7 @@ var TRMNLPicker = (() => {
|
||||
* @throws {Error} If API fetch fails when models or palettes are not provided
|
||||
*
|
||||
* @example
|
||||
* // Fetch models and palettes from API
|
||||
* // Fetch models and palettes from API (or use cached data if available)
|
||||
* const picker = await TRMNLPicker.create('screen-picker')
|
||||
*
|
||||
* // Provide your own data
|
||||
@@ -45,6 +92,13 @@ var TRMNLPicker = (() => {
|
||||
*/
|
||||
static async create(formId, options = {}) {
|
||||
let { models, palettes, localStorageKey } = options;
|
||||
if (!models && !palettes) {
|
||||
const cached = _TRMNLPicker._getCachedApiData();
|
||||
if (cached) {
|
||||
models = cached.models;
|
||||
palettes = cached.palettes;
|
||||
}
|
||||
}
|
||||
if (!models) {
|
||||
try {
|
||||
const response = await fetch(`${_TRMNLPicker.API_BASE_URL}/api/models`);
|
||||
@@ -69,6 +123,9 @@ var TRMNLPicker = (() => {
|
||||
throw new Error(`TRMNLPicker: Failed to fetch palettes from API: ${error.message}`);
|
||||
}
|
||||
}
|
||||
if (!options.models && !options.palettes) {
|
||||
_TRMNLPicker._setCachedApiData(models, palettes);
|
||||
}
|
||||
return new _TRMNLPicker(formId, { models, palettes, localStorageKey });
|
||||
}
|
||||
constructor(formIdOrElement, options = {}) {
|
||||
@@ -268,7 +325,6 @@ var TRMNLPicker = (() => {
|
||||
const event = new CustomEvent("trmnl:change", {
|
||||
detail: {
|
||||
origin,
|
||||
screenClasses: this.screenClasses,
|
||||
...this.state
|
||||
},
|
||||
bubbles: true
|
||||
@@ -376,7 +432,7 @@ var TRMNLPicker = (() => {
|
||||
}
|
||||
/**
|
||||
* Get CSS classes for the current picker configuration
|
||||
* @public
|
||||
* @private
|
||||
* @returns {Array<string>} Array of CSS class names for Framework CSS rendering
|
||||
*
|
||||
* Generated classes (in order):
|
||||
@@ -392,7 +448,7 @@ var TRMNLPicker = (() => {
|
||||
* const classes = picker.screenClasses
|
||||
* // ['screen', 'screen--1bit', 'screen--v2', 'screen--md', 'screen--1x']
|
||||
*/
|
||||
get screenClasses() {
|
||||
get _screenClasses() {
|
||||
const model = this._state.model;
|
||||
const palette = this._state.palette;
|
||||
if (!model) {
|
||||
@@ -530,7 +586,10 @@ var TRMNLPicker = (() => {
|
||||
* model: Object,
|
||||
* palette: Object,
|
||||
* isPortrait: boolean,
|
||||
* isDarkMode: boolean
|
||||
* isDarkMode: boolean,
|
||||
* screenClasses: Array<string>,
|
||||
* width: number,
|
||||
* height: number
|
||||
* }} State object containing model (full model object from API), palette (full palette object from API), isPortrait flag, and isDarkMode flag
|
||||
*
|
||||
* @example
|
||||
@@ -539,11 +598,32 @@ var TRMNLPicker = (() => {
|
||||
* // model: { name: 'og_plus', label: 'OG+', width: 800, height: 480, ... },
|
||||
* // palette: { id: '123', name: 'Black', framework_class: 'screen--1bit', ... },
|
||||
* // isPortrait: false,
|
||||
* // isDarkMode: false
|
||||
* // isDarkMode: false,
|
||||
* // screenClasses: ['screen', 'screen--1bit', 'screen--v2', 'screen--md', 'screen--1x'],
|
||||
* // width: 800,
|
||||
* // height: 480
|
||||
* // }
|
||||
*/
|
||||
get state() {
|
||||
return { ...this._state };
|
||||
return {
|
||||
screenClasses: this._screenClasses,
|
||||
...this._dimensions,
|
||||
...this._state
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Get current dimensions (width and height) of the screen in pixels
|
||||
* @private
|
||||
* @returns {{ width: number, height: number }} Object with width and height properties
|
||||
*/
|
||||
get _dimensions() {
|
||||
const model = this._state.model;
|
||||
let width = model.width / model.scale_factor;
|
||||
let height = model.height / model.scale_factor;
|
||||
if (this._state.isPortrait) {
|
||||
[width, height] = [height, width];
|
||||
}
|
||||
return { width, height };
|
||||
}
|
||||
/**
|
||||
* Clean up event listeners and references
|
||||
|
||||
Vendored
+2
-2
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+3
-3
File diff suppressed because one or more lines are too long
+17
-83
@@ -62,12 +62,6 @@
|
||||
<ul class='list-reset py1-ul pl1'>
|
||||
<li class='h5'><span>Instance members</span></li>
|
||||
|
||||
<li><a
|
||||
href='#trmnlpickerscreenclasses'
|
||||
class='regular pre-open'>
|
||||
#screenClasses
|
||||
</a></li>
|
||||
|
||||
<li><a
|
||||
href='#trmnlpickerparams'
|
||||
class='regular pre-open'>
|
||||
@@ -184,6 +178,16 @@
|
||||
<p>Dark mode flag</p>
|
||||
</li>
|
||||
|
||||
<li><code>detail.width</code> <a href="https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number">number</a>
|
||||
|
||||
<p>Current width of the screen in pixels</p>
|
||||
</li>
|
||||
|
||||
<li><code>detail.height</code> <a href="https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number">number</a>
|
||||
|
||||
<p>Current height of the screen in pixels</p>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@@ -387,6 +391,7 @@ picker.<span class="hljs-property">formElement</span>.<span class="hljs-title fu
|
||||
|
||||
|
||||
<p>Create a TRMNLPicker instance, fetching data from TRMNL API if not provided</p>
|
||||
<p>Automatically caches API responses in localStorage for 24 hours to reduce network requests.</p>
|
||||
|
||||
<div class='pre p1 fill-light mt0'>create(formId: any, options: <a href="https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object">Object</a>, formIdOrElement: (<a href="https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String">string</a> | <a href="https://developer.mozilla.org/docs/Web/API/Element">Element</a>)): <a href="https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a><<a href="#trmnlpicker">TRMNLPicker</a>></div>
|
||||
|
||||
@@ -504,7 +509,7 @@ picker.<span class="hljs-property">formElement</span>.<span class="hljs-title fu
|
||||
<div class='py1 quiet mt1 prose-big'>Example</div>
|
||||
|
||||
|
||||
<pre class='p1 overflow-auto round fill-light'><span class="hljs-comment">// Fetch models and palettes from API</span>
|
||||
<pre class='p1 overflow-auto round fill-light'><span class="hljs-comment">// Fetch models and palettes from API (or use cached data if available)</span>
|
||||
<span class="hljs-keyword">const</span> picker = <span class="hljs-keyword">await</span> <span class="hljs-title class_">TRMNLPicker</span>.<span class="hljs-title function_">create</span>(<span class="hljs-string">'screen-picker'</span>)
|
||||
|
||||
<span class="hljs-comment">// Provide your own data</span>
|
||||
@@ -532,80 +537,6 @@ picker.<span class="hljs-property">formElement</span>.<span class="hljs-title fu
|
||||
<div class='py1 quiet mt1 prose-big'>Instance Members</div>
|
||||
<div class="clearfix">
|
||||
|
||||
<div class='border-bottom' id='trmnlpickerscreenclasses'>
|
||||
<div class="clearfix small pointer toggle-sibling">
|
||||
<div class="py1 contain">
|
||||
<a class='icon pin-right py1 dark-link caret-right'>▸</a>
|
||||
<span class='code strong strong truncate'>screenClasses</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class='clearfix toggle-target'>
|
||||
<section class='p2 mb2 clearfix bg-white minishadow'>
|
||||
|
||||
|
||||
|
||||
<p>Get CSS classes for the current picker configuration</p>
|
||||
|
||||
<div class='pre p1 fill-light mt0'>screenClasses</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class='py1 quiet mt1 prose-big'>Returns</div>
|
||||
<code><a href="https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array">Array</a><<a href="https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String">string</a>></code>:
|
||||
Array of CSS class names for Framework CSS rendering
|
||||
<p>Generated classes (in order):</p>
|
||||
<ol>
|
||||
<li>'screen' - Base class (always present)</li>
|
||||
<li>palette.framework_class - From selected palette (e.g., 'screen--1bit')</li>
|
||||
<li>model.css.classes.device - From model API (e.g., 'screen--v2')</li>
|
||||
<li>model.css.classes.size - From model API (e.g., 'screen--md')</li>
|
||||
<li>'screen--portrait' - Only when portrait orientation is enabled</li>
|
||||
<li>'screen--1x' - Scale indicator (always 1x)</li>
|
||||
<li>'screen--dark-mode' - Only when dark mode is enabled</li>
|
||||
</ol>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class='py1 quiet mt1 prose-big'>Example</div>
|
||||
|
||||
|
||||
<pre class='p1 overflow-auto round fill-light'><span class="hljs-keyword">const</span> classes = picker.<span class="hljs-property">screenClasses</span>
|
||||
<span class="hljs-comment">// ['screen', 'screen--1bit', 'screen--v2', 'screen--md', 'screen--1x']</span></pre>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class='border-bottom' id='trmnlpickerparams'>
|
||||
<div class="clearfix small pointer toggle-sibling">
|
||||
<div class="py1 contain">
|
||||
@@ -868,7 +799,7 @@ picker.<span class="hljs-title function_">setParams</span>({
|
||||
|
||||
|
||||
<div class='py1 quiet mt1 prose-big'>Returns</div>
|
||||
<code>{model: <a href="https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object">Object</a>, palette: <a href="https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object">Object</a>, isPortrait: <a href="https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean">boolean</a>, isDarkMode: <a href="https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean">boolean</a>}</code>:
|
||||
<code>{model: <a href="https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object">Object</a>, palette: <a href="https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object">Object</a>, isPortrait: <a href="https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean">boolean</a>, isDarkMode: <a href="https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean">boolean</a>, screenClasses: <a href="https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array">Array</a><<a href="https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String">string</a>>, width: <a href="https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number">number</a>, height: <a href="https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number">number</a>}</code>:
|
||||
State object containing model (full model object from API), palette (full palette object from API), isPortrait flag, and isDarkMode flag
|
||||
|
||||
|
||||
@@ -888,7 +819,10 @@ picker.<span class="hljs-title function_">setParams</span>({
|
||||
<span class="hljs-comment">// model: { name: 'og_plus', label: 'OG+', width: 800, height: 480, ... },</span>
|
||||
<span class="hljs-comment">// palette: { id: '123', name: 'Black', framework_class: 'screen--1bit', ... },</span>
|
||||
<span class="hljs-comment">// isPortrait: false,</span>
|
||||
<span class="hljs-comment">// isDarkMode: false</span>
|
||||
<span class="hljs-comment">// isDarkMode: false,</span>
|
||||
<span class="hljs-comment">// screenClasses: ['screen', 'screen--1bit', 'screen--v2', 'screen--md', 'screen--1x'],</span>
|
||||
<span class="hljs-comment">// width: 800,</span>
|
||||
<span class="hljs-comment">// height: 480</span>
|
||||
<span class="hljs-comment">// }</span></pre>
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user